diff options
Diffstat (limited to 'sound/soc/codecs/wm8994_herring.c')
-rwxr-xr-x | sound/soc/codecs/wm8994_herring.c | 3988 |
1 files changed, 3988 insertions, 0 deletions
diff --git a/sound/soc/codecs/wm8994_herring.c b/sound/soc/codecs/wm8994_herring.c new file mode 100755 index 0000000..28e2320 --- /dev/null +++ b/sound/soc/codecs/wm8994_herring.c @@ -0,0 +1,3988 @@ +/* + * wm8994_crespo.c -- WM8994 ALSA Soc Audio driver related Aries + * + * Copyright (C) 2010 Samsung Electronics. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include <sound/soc.h> +#include <sound/soc-dapm.h> +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/gpio.h> +#include <linux/clk.h> +#include <plat/gpio-cfg.h> +#include <plat/map-base.h> +#include <mach/regs-clock.h> +#include "wm8994_samsung.h" +#include "../../../arch/arm/mach-s5pv210/herring.h" +#ifdef CONFIG_SND_VOODOO +#include "wm8994_voodoo.h" +#endif + +/* + * Debug Feature + */ +#define SUBJECT "wm8994_crespo.c" + +/* + * Definitions of tunning volumes for wm8994 + */ + +struct gain_info_t cdma_playback_gain_table[PLAYBACK_GAIN_NUM] = { + { /* COMMON */ + .mode = COMMON_SET_BIT, + .reg = WM8994_DAC1_LEFT_VOLUME, /* 610h */ + .mask = WM8994_DAC1L_VOL_MASK, + .gain = WM8994_DAC1_VU | 0xC0 + }, { + .mode = COMMON_SET_BIT, + .reg = WM8994_DAC1_RIGHT_VOLUME, /* 611h */ + .mask = WM8994_DAC1R_VOL_MASK, + .gain = WM8994_DAC1_VU | 0xC0 + }, { + .mode = COMMON_SET_BIT, + .reg = WM8994_AIF1_DAC1_LEFT_VOLUME, /* 402h */ + .mask = WM8994_AIF1DAC1L_VOL_MASK, + .gain = WM8994_AIF1DAC1_VU | 0xC0 + }, { + .mode = COMMON_SET_BIT, + .reg = WM8994_AIF1_DAC1_RIGHT_VOLUME, /* 403h */ + .mask = WM8994_AIF1DAC1R_VOL_MASK, + .gain = WM8994_AIF1DAC1_VU | 0xC0 + }, { /* RCV */ + .mode = PLAYBACK_RCV, + .reg = WM8994_OUTPUT_MIXER_5, /* 31h */ + .mask = WM8994_DACL_MIXOUTL_VOL_MASK, + .gain = 0x0 << WM8994_DACL_MIXOUTL_VOL_SHIFT + }, { + .mode = PLAYBACK_RCV, + .reg = WM8994_OUTPUT_MIXER_6, /* 32h */ + .mask = WM8994_DACR_MIXOUTR_VOL_MASK, + .gain = 0x0 << WM8994_DACR_MIXOUTR_VOL_SHIFT + }, { + .mode = PLAYBACK_RCV, + .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */ + .mask = WM8994_MIXOUTL_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x3D + }, { + .mode = PLAYBACK_RCV, + .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */ + .mask = WM8994_MIXOUTR_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x3D + }, { + .mode = PLAYBACK_RCV, + .reg = WM8994_HPOUT2_VOLUME, /* 1Fh */ + .mask = WM8994_HPOUT2_VOL_MASK, + .gain = 0x0 << WM8994_HPOUT2_VOL_SHIFT + }, { /* SPK */ + .mode = PLAYBACK_SPK, + .reg = WM8994_SPKMIXL_ATTENUATION, /* 22h */ + .mask = WM8994_SPKMIXL_VOL_MASK, + .gain = 0x0 + }, { + .mode = PLAYBACK_SPK, + .reg = WM8994_SPKMIXR_ATTENUATION, /* 23h */ + .mask = WM8994_SPKMIXR_VOL_MASK, + .gain = 0x0 + }, { + .mode = PLAYBACK_SPK, + .reg = WM8994_SPEAKER_VOLUME_LEFT, /* 26h */ + .mask = WM8994_SPKOUTL_VOL_MASK, + .gain = WM8994_SPKOUT_VU | 0x3E /* +5dB */ + }, { + .mode = PLAYBACK_SPK, + .reg = WM8994_SPEAKER_VOLUME_RIGHT, /* 27h */ + .mask = WM8994_SPKOUTR_VOL_MASK, + .gain = 0 + }, { + .mode = PLAYBACK_SPK, + .reg = WM8994_CLASSD, /* 25h */ + .mask = WM8994_SPKOUTL_BOOST_MASK, + .gain = 0x05 << WM8994_SPKOUTL_BOOST_SHIFT /* +7.5dB */ + }, { + .mode = PLAYBACK_SPK, + .reg = WM8994_AIF1_DAC1_LEFT_VOLUME, /* 402h */ + .mask = WM8994_AIF1DAC1L_VOL_MASK, + .gain = WM8994_AIF1DAC1_VU | 0xB8 /* -2.625dB */ + }, { + .mode = PLAYBACK_SPK, + .reg = WM8994_AIF1_DAC1_RIGHT_VOLUME, /* 403h */ + .mask = WM8994_AIF1DAC1R_VOL_MASK, + .gain = WM8994_AIF1DAC1_VU | 0xB8 /* -2.625dB */ + }, { /* HP */ + .mode = PLAYBACK_HP, + .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */ + .mask = WM8994_HPOUT1L_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x31 /* -8dB */ + }, { + .mode = PLAYBACK_HP, + .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */ + .mask = WM8994_HPOUT1R_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x31 /* -8dB */ + }, { + .mode = PLAYBACK_HP, + .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */ + .mask = WM8994_MIXOUTL_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x39 + }, { + .mode = PLAYBACK_HP, + .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */ + .mask = WM8994_MIXOUTR_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x39 + }, { /* SPK_HP */ + .mode = PLAYBACK_SPK_HP, + .reg = WM8994_SPKMIXL_ATTENUATION, /* 22h */ + .mask = WM8994_SPKMIXL_VOL_MASK, + .gain = 0x0 + }, { + .mode = PLAYBACK_SPK_HP, + .reg = WM8994_SPKMIXR_ATTENUATION, /* 23h */ + .mask = WM8994_SPKMIXR_VOL_MASK, + .gain = 0x0 + }, { + .mode = PLAYBACK_SPK_HP, + .reg = WM8994_SPEAKER_VOLUME_LEFT, /* 26h */ + .mask = WM8994_SPKOUTL_VOL_MASK, + .gain = WM8994_SPKOUT_VU | 0x3E + }, { + .mode = PLAYBACK_SPK_HP, + .reg = WM8994_SPEAKER_VOLUME_RIGHT, /* 27h */ + .mask = WM8994_SPKOUTR_VOL_MASK, + .gain = 0x0 + }, { + .mode = PLAYBACK_SPK_HP, + .reg = WM8994_CLASSD, /* 25h */ + .mask = WM8994_SPKOUTL_BOOST_MASK, + .gain = 0x5 << WM8994_SPKOUTL_BOOST_SHIFT + }, { + .mode = PLAYBACK_SPK_HP, + .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */ + .mask = WM8994_HPOUT1L_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x1E + }, { + .mode = PLAYBACK_SPK_HP, + .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */ + .mask = WM8994_HPOUT1R_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x1E + }, { + .mode = PLAYBACK_SPK_HP, + .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */ + .mask = WM8994_MIXOUTL_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x39 + }, { + .mode = PLAYBACK_SPK_HP, + .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */ + .mask = WM8994_MIXOUTR_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x39 + }, { /* RING_SPK */ + .mode = PLAYBACK_RING_SPK, + .reg = WM8994_SPEAKER_VOLUME_LEFT, /* 26h */ + .mask = WM8994_SPKOUTL_VOL_MASK, + .gain = WM8994_SPKOUT_VU | 0x3E + }, { + .mode = PLAYBACK_RING_SPK, + .reg = WM8994_CLASSD, /* 25h */ + .mask = WM8994_SPKOUTL_BOOST_MASK, + .gain = 0x5 << WM8994_SPKOUTL_BOOST_SHIFT + }, { /* RING_HP */ + .mode = PLAYBACK_RING_HP, + .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */ + .mask = WM8994_HPOUT1L_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x34 + }, { + .mode = PLAYBACK_RING_HP, + .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */ + .mask = WM8994_HPOUT1R_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x34 + }, { + .mode = PLAYBACK_RING_HP, + .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */ + .mask = WM8994_MIXOUTL_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x39 + }, { + .mode = PLAYBACK_RING_HP, + .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */ + .mask = WM8994_MIXOUTR_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x39 + }, { /* RING_SPK_HP */ + .mode = PLAYBACK_RING_SPK_HP, + .reg = WM8994_SPEAKER_VOLUME_LEFT, /* 26h */ + .mask = WM8994_SPKOUTL_VOL_MASK, + .gain = WM8994_SPKOUT_VU | 0x3E + }, { + .mode = PLAYBACK_RING_SPK_HP, + .reg = WM8994_CLASSD, /* 25h */ + .mask = WM8994_SPKOUTL_BOOST_MASK, + .gain = 0x5 << WM8994_SPKOUTL_BOOST_SHIFT + }, { + .mode = PLAYBACK_RING_SPK_HP, + .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */ + .mask = WM8994_HPOUT1L_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x1E + }, { + .mode = PLAYBACK_RING_SPK_HP, + .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */ + .mask = WM8994_HPOUT1R_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x1E + }, { /* HP_NO_MIC */ + .mode = PLAYBACK_HP_NO_MIC, + .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */ + .mask = WM8994_HPOUT1L_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x36 /* -3dB */ + }, { + .mode = PLAYBACK_HP_NO_MIC, + .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */ + .mask = WM8994_HPOUT1R_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x36 /* -3dB */ + }, { + .mode = PLAYBACK_HP_NO_MIC, + .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */ + .mask = WM8994_MIXOUTL_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x39 + }, { + .mode = PLAYBACK_HP_NO_MIC, + .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */ + .mask = WM8994_MIXOUTR_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x39 + }, +}; + +struct gain_info_t cdma_voicecall_gain_table[VOICECALL_GAIN_NUM] = { + { /* COMMON */ + .mode = COMMON_SET_BIT, + .reg = WM8994_DAC1_LEFT_VOLUME, /* 610h */ + .mask = WM8994_DAC1L_VOL_MASK, + .gain = WM8994_DAC1_VU | 0xC0 /* 0dB */ + }, { + .mode = COMMON_SET_BIT, + .reg = WM8994_DAC1_RIGHT_VOLUME, /* 611h */ + .mask = WM8994_DAC1R_VOL_MASK, + .gain = WM8994_DAC1_VU | 0xC0 /* 0dB */ + }, { + .mode = COMMON_SET_BIT, + .reg = WM8994_AIF1_DAC1_LEFT_VOLUME, /* 402h */ + .mask = WM8994_AIF1DAC1L_VOL_MASK, + .gain = WM8994_AIF1DAC1_VU | 0xC0 /* 0dB */ + }, { + .mode = COMMON_SET_BIT, + .reg = WM8994_AIF1_DAC1_RIGHT_VOLUME, /* 403h */ + .mask = WM8994_AIF1DAC1R_VOL_MASK, + .gain = WM8994_AIF1DAC1_VU | 0xC0 /* 0dB */ + }, { + .mode = COMMON_SET_BIT, + .reg = WM8994_DAC2_LEFT_VOLUME, /* 612h */ + .mask = WM8994_DAC2L_VOL_MASK, + .gain = WM8994_DAC2_VU | 0xC0 /* 0dB */ + }, { + .mode = COMMON_SET_BIT, + .reg = WM8994_DAC2_RIGHT_VOLUME, /* 613h */ + .mask = WM8994_DAC2R_VOL_MASK, + .gain = WM8994_DAC2_VU | 0xC0 /* 0dB */ + }, { /* RCV */ + .mode = VOICECALL_RCV, + .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */ + .mask = WM8994_IN1L_VOL_MASK, + .gain = WM8994_IN1L_VU | 0x0C /* +15dB */ + }, { + .mode = VOICECALL_RCV, + .reg = WM8994_INPUT_MIXER_3, /* 29h */ + .mask = WM8994_IN1L_MIXINL_VOL_MASK | WM8994_MIXOUTL_MIXINL_VOL_MASK, + .gain = 0x10 /* +30dB */ + }, { + .mode = VOICECALL_RCV, + .reg = WM8994_OUTPUT_MIXER_5, /* 31h */ + .mask = WM8994_DACL_MIXOUTL_VOL_MASK, + .gain = 0x0 << WM8994_DACL_MIXOUTL_VOL_SHIFT + }, { + .mode = VOICECALL_RCV, + .reg = WM8994_OUTPUT_MIXER_6, /* 32h */ + .mask = WM8994_DACR_MIXOUTR_VOL_MASK, + .gain = 0x0 << WM8994_DACR_MIXOUTR_VOL_SHIFT + }, { + .mode = VOICECALL_RCV, + .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */ + .mask = WM8994_MIXOUTL_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x3F + }, { + .mode = VOICECALL_RCV, + .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */ + .mask = WM8994_MIXOUTR_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x3F + }, { + .mode = VOICECALL_RCV, + .reg = WM8994_HPOUT2_VOLUME, /* 1Fh */ + .mask = WM8994_HPOUT2_VOL_MASK, + .gain = 0x0 << WM8994_HPOUT2_VOL_SHIFT + }, { /* SPK */ + .mode = VOICECALL_SPK, + .reg = WM8994_INPUT_MIXER_3, /* 29h */ + .mask = WM8994_IN1L_MIXINL_VOL_MASK | WM8994_MIXOUTL_MIXINL_VOL_MASK, + .gain = 0x10 /* Mic +7.5dB */ + }, { + .mode = VOICECALL_SPK, + .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */ + .mask = WM8994_IN1L_VOL_MASK, + .gain = WM8994_IN1L_VU | 0x12 /* Mic +30dB */ + }, { + .mode = VOICECALL_SPK, + .reg = WM8994_SPKMIXL_ATTENUATION, /* 22h */ + .mask = WM8994_SPKMIXL_VOL_MASK, + .gain = 0x0 /* Speaker +0dB */ + }, { + .mode = VOICECALL_SPK, + .reg = WM8994_SPKMIXR_ATTENUATION, /* 23h */ + .mask = WM8994_SPKMIXR_VOL_MASK, + .gain = 0x0 /* Speaker +0dB */ + }, { + .mode = VOICECALL_SPK, + .reg = WM8994_SPEAKER_VOLUME_LEFT, /* 26h */ + .mask = WM8994_SPKOUTL_VOL_MASK, + .gain = WM8994_SPKOUT_VU | 0x3F /* Left Speaker +3dB */ + }, { + .mode = VOICECALL_SPK, + .reg = WM8994_SPEAKER_VOLUME_RIGHT, /* 27h */ + .mask = WM8994_SPKOUTR_VOL_MASK, /* Right Speaker -57dB */ + .gain = 0x0 + }, { + .mode = VOICECALL_SPK, + .reg = WM8994_CLASSD, /* 25h */ + .mask = WM8994_SPKOUTL_BOOST_MASK, + .gain = 0x7 << WM8994_SPKOUTL_BOOST_SHIFT /* Left spaker +12dB */ + }, { /* HP */ + .mode = VOICECALL_HP, + .reg = WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, /* 1Ah */ + .mask = WM8994_IN1R_VOL_MASK, + .gain = WM8994_IN1R_VU | 0x1D + }, { + .mode = VOICECALL_HP, + .reg = WM8994_INPUT_MIXER_4, /* 2Ah */ + .mask = WM8994_IN1R_MIXINR_VOL_MASK | WM8994_MIXOUTR_MIXINR_VOL_MASK, + .gain = 0x0 + }, { + .mode = VOICECALL_HP, + .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */ + .mask = WM8994_MIXOUTL_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x39 + }, { + .mode = VOICECALL_HP, + .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */ + .mask = WM8994_MIXOUTR_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x39 + }, { + .mode = VOICECALL_HP, + .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */ + .mask = WM8994_HPOUT1L_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x30 + }, { + .mode = VOICECALL_HP, + .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */ + .mask = WM8994_HPOUT1R_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x30 + }, { /* HP_NO_MIC */ + .mode = VOICECALL_HP_NO_MIC, + .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */ + .mask = WM8994_IN1L_VOL_MASK, + .gain = WM8994_IN1L_VU | 0x12 /* +10.5dB */ + }, { + .mode = VOICECALL_HP_NO_MIC, + .reg = WM8994_INPUT_MIXER_3, /* 29h */ + .mask = WM8994_IN1L_MIXINL_VOL_MASK | WM8994_MIXOUTL_MIXINL_VOL_MASK, + .gain = 0x10 + }, { + .mode = VOICECALL_HP_NO_MIC, + .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */ + .mask = WM8994_MIXOUTL_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x39 + }, { + .mode = VOICECALL_HP_NO_MIC, + .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */ + .mask = WM8994_MIXOUTR_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x39 + }, { + .mode = VOICECALL_HP_NO_MIC, + .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */ + .mask = WM8994_HPOUT1L_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x30 + }, { + .mode = VOICECALL_HP_NO_MIC, + .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */ + .mask = WM8994_HPOUT1R_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x30 + }, { /* TTY_VCO */ + .mode = VOICECALL_TTY_VCO, + .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */ + .mask = WM8994_IN1L_VOL_MASK, + .gain = WM8994_IN1L_VU | 0x15 /* +10.5dB */ + }, { + .mode = VOICECALL_TTY_VCO, + .reg = WM8994_INPUT_MIXER_3, /* 29h */ + .mask = WM8994_IN1L_MIXINL_VOL_MASK | WM8994_MIXOUTL_MIXINL_VOL_MASK, + .gain = 0x0 + }, { /* TTY_HCO */ + .mode = VOICECALL_TTY_HCO, + .reg = WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, /* 1Ah */ + .mask = WM8994_IN1R_VOL_MASK, + .gain = WM8994_IN1R_VU | 0x13 /* +12dB */ + }, { + .mode = VOICECALL_TTY_HCO, + .reg = WM8994_INPUT_MIXER_4, /* 2Ah */ + .mask = WM8994_IN1R_MIXINR_VOL_MASK | WM8994_MIXOUTR_MIXINR_VOL_MASK, + .gain = 0x0 + }, { /* TTY_FULL */ + .mode = VOICECALL_TTY_FULL, + .reg = WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, /* 1Ah */ + .mask = WM8994_IN1R_VOL_MASK, + .gain = WM8994_IN1R_VU | 0x13 /* +12dB */ + }, { + .mode = VOICECALL_TTY_FULL, + .reg = WM8994_INPUT_MIXER_4, /* 2Ah */ + .mask = WM8994_IN1R_MIXINR_VOL_MASK | WM8994_MIXOUTR_MIXINR_VOL_MASK, + .gain = 0x0 + }, +}; + +struct gain_info_t playback_gain_table[PLAYBACK_GAIN_NUM] = { + { /* COMMON */ + .mode = COMMON_SET_BIT, + .reg = WM8994_DAC1_LEFT_VOLUME, /* 610h */ + .mask = WM8994_DAC1L_VOL_MASK, + .gain = WM8994_DAC1_VU | 0xC0 + }, { + .mode = COMMON_SET_BIT, + .reg = WM8994_DAC1_RIGHT_VOLUME, /* 611h */ + .mask = WM8994_DAC1R_VOL_MASK, + .gain = WM8994_DAC1_VU | 0xC0 + }, { + .mode = COMMON_SET_BIT, + .reg = WM8994_AIF1_DAC1_LEFT_VOLUME, /* 402h */ + .mask = WM8994_AIF1DAC1L_VOL_MASK, + .gain = WM8994_AIF1DAC1_VU | 0xC0 + }, { + .mode = COMMON_SET_BIT, + .reg = WM8994_AIF1_DAC1_RIGHT_VOLUME, /* 403h */ + .mask = WM8994_AIF1DAC1R_VOL_MASK, + .gain = WM8994_AIF1DAC1_VU | 0xC0 + }, { /* RCV */ + .mode = PLAYBACK_RCV, + .reg = WM8994_OUTPUT_MIXER_5, /* 31h */ + .mask = WM8994_DACL_MIXOUTL_VOL_MASK, + .gain = 0x0 << WM8994_DACL_MIXOUTL_VOL_SHIFT + }, { + .mode = PLAYBACK_RCV, + .reg = WM8994_OUTPUT_MIXER_6, /* 32h */ + .mask = WM8994_DACR_MIXOUTR_VOL_MASK, + .gain = 0x0 << WM8994_DACR_MIXOUTR_VOL_SHIFT + }, { + .mode = PLAYBACK_RCV, + .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */ + .mask = WM8994_MIXOUTL_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x3D + }, { + .mode = PLAYBACK_RCV, + .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */ + .mask = WM8994_MIXOUTR_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x3D + }, { + .mode = PLAYBACK_RCV, + .reg = WM8994_HPOUT2_VOLUME, /* 1Fh */ + .mask = WM8994_HPOUT2_VOL_MASK, + .gain = 0x0 << WM8994_HPOUT2_VOL_SHIFT + }, { /* SPK */ + .mode = PLAYBACK_SPK, + .reg = WM8994_SPKMIXL_ATTENUATION, /* 22h */ + .mask = WM8994_SPKMIXL_VOL_MASK, + .gain = 0x0 + }, { + .mode = PLAYBACK_SPK, + .reg = WM8994_SPKMIXR_ATTENUATION, /* 23h */ + .mask = WM8994_SPKMIXR_VOL_MASK, + .gain = 0x0 + }, { + .mode = PLAYBACK_SPK, + .reg = WM8994_SPEAKER_VOLUME_LEFT, /* 26h */ + .mask = WM8994_SPKOUTL_VOL_MASK, + .gain = WM8994_SPKOUT_VU | 0x3E /* +5dB */ + }, { + .mode = PLAYBACK_SPK, + .reg = WM8994_SPEAKER_VOLUME_RIGHT, /* 27h */ + .mask = WM8994_SPKOUTR_VOL_MASK, + .gain = 0 + }, { + .mode = PLAYBACK_SPK, + .reg = WM8994_CLASSD, /* 25h */ + .mask = WM8994_SPKOUTL_BOOST_MASK, + .gain = 0x05 << WM8994_SPKOUTL_BOOST_SHIFT /* +7.5dB */ + }, { + .mode = PLAYBACK_SPK, + .reg = WM8994_AIF1_DAC1_LEFT_VOLUME, /* 402h */ + .mask = WM8994_AIF1DAC1L_VOL_MASK, + .gain = WM8994_AIF1DAC1_VU | 0xB8 /* -2.625dB */ + }, { + .mode = PLAYBACK_SPK, + .reg = WM8994_AIF1_DAC1_RIGHT_VOLUME, /* 403h */ + .mask = WM8994_AIF1DAC1R_VOL_MASK, + .gain = WM8994_AIF1DAC1_VU | 0xB8 /* -2.625dB */ + }, { /* HP */ + .mode = PLAYBACK_HP, + .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */ + .mask = WM8994_HPOUT1L_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x31 /* -8dB */ + }, { + .mode = PLAYBACK_HP, + .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */ + .mask = WM8994_HPOUT1R_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x31 /* -8dB */ + }, { + .mode = PLAYBACK_HP, + .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */ + .mask = WM8994_MIXOUTL_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x39 + }, { + .mode = PLAYBACK_HP, + .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */ + .mask = WM8994_MIXOUTR_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x39 + }, { /* SPK_HP */ + .mode = PLAYBACK_SPK_HP, + .reg = WM8994_SPKMIXL_ATTENUATION, /* 22h */ + .mask = WM8994_SPKMIXL_VOL_MASK, + .gain = 0x0 + }, { + .mode = PLAYBACK_SPK_HP, + .reg = WM8994_SPKMIXR_ATTENUATION, /* 23h */ + .mask = WM8994_SPKMIXR_VOL_MASK, + .gain = 0x0 + }, { + .mode = PLAYBACK_SPK_HP, + .reg = WM8994_SPEAKER_VOLUME_LEFT, /* 26h */ + .mask = WM8994_SPKOUTL_VOL_MASK, + .gain = WM8994_SPKOUT_VU | 0x3E + }, { + .mode = PLAYBACK_SPK_HP, + .reg = WM8994_SPEAKER_VOLUME_RIGHT, /* 27h */ + .mask = WM8994_SPKOUTR_VOL_MASK, + .gain = 0x0 + }, { + .mode = PLAYBACK_SPK_HP, + .reg = WM8994_CLASSD, /* 25h */ + .mask = WM8994_SPKOUTL_BOOST_MASK, + .gain = 0x5 << WM8994_SPKOUTL_BOOST_SHIFT + }, { + .mode = PLAYBACK_SPK_HP, + .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */ + .mask = WM8994_HPOUT1L_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x1E + }, { + .mode = PLAYBACK_SPK_HP, + .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */ + .mask = WM8994_HPOUT1R_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x1E + }, { + .mode = PLAYBACK_SPK_HP, + .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */ + .mask = WM8994_MIXOUTL_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x39 + }, { + .mode = PLAYBACK_SPK_HP, + .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */ + .mask = WM8994_MIXOUTR_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x39 + }, { /* RING_SPK */ + .mode = PLAYBACK_RING_SPK, + .reg = WM8994_SPEAKER_VOLUME_LEFT, /* 26h */ + .mask = WM8994_SPKOUTL_VOL_MASK, + .gain = WM8994_SPKOUT_VU | 0x3E + }, { + .mode = PLAYBACK_RING_SPK, + .reg = WM8994_CLASSD, /* 25h */ + .mask = WM8994_SPKOUTL_BOOST_MASK, + .gain = 0x5 << WM8994_SPKOUTL_BOOST_SHIFT + }, { /* RING_HP */ + .mode = PLAYBACK_RING_HP, + .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */ + .mask = WM8994_HPOUT1L_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x34 + }, { + .mode = PLAYBACK_RING_HP, + .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */ + .mask = WM8994_HPOUT1R_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x34 + }, { + .mode = PLAYBACK_RING_HP, + .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */ + .mask = WM8994_MIXOUTL_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x39 + }, { + .mode = PLAYBACK_RING_HP, + .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */ + .mask = WM8994_MIXOUTR_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x39 + }, { /* RING_SPK_HP */ + .mode = PLAYBACK_RING_SPK_HP, + .reg = WM8994_SPEAKER_VOLUME_LEFT, /* 26h */ + .mask = WM8994_SPKOUTL_VOL_MASK, + .gain = WM8994_SPKOUT_VU | 0x3E + }, { + .mode = PLAYBACK_RING_SPK_HP, + .reg = WM8994_CLASSD, /* 25h */ + .mask = WM8994_SPKOUTL_BOOST_MASK, + .gain = 0x5 << WM8994_SPKOUTL_BOOST_SHIFT + }, { + .mode = PLAYBACK_RING_SPK_HP, + .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */ + .mask = WM8994_HPOUT1L_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x1E + }, { + .mode = PLAYBACK_RING_SPK_HP, + .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */ + .mask = WM8994_HPOUT1R_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x1E + }, { /* HP_NO_MIC */ + .mode = PLAYBACK_HP_NO_MIC, + .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */ + .mask = WM8994_HPOUT1L_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x36 /* -3dB */ + }, { + .mode = PLAYBACK_HP_NO_MIC, + .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */ + .mask = WM8994_HPOUT1R_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x36 /* -3dB */ + }, { + .mode = PLAYBACK_HP_NO_MIC, + .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */ + .mask = WM8994_MIXOUTL_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x39 + }, { + .mode = PLAYBACK_HP_NO_MIC, + .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */ + .mask = WM8994_MIXOUTR_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x39 + }, +}; + +struct gain_info_t voicecall_gain_table[VOICECALL_GAIN_NUM] = { + { /* COMMON */ + .mode = COMMON_SET_BIT, + .reg = WM8994_DAC1_LEFT_VOLUME, /* 610h */ + .mask = WM8994_DAC1L_VOL_MASK, + .gain = WM8994_DAC1_VU | 0xC0 /* 0dB */ + }, { + .mode = COMMON_SET_BIT, + .reg = WM8994_DAC1_RIGHT_VOLUME, /* 611h */ + .mask = WM8994_DAC1R_VOL_MASK, + .gain = WM8994_DAC1_VU | 0xC0 /* 0dB */ + }, { + .mode = COMMON_SET_BIT, + .reg = WM8994_AIF1_DAC1_LEFT_VOLUME, /* 402h */ + .mask = WM8994_AIF1DAC1L_VOL_MASK, + .gain = WM8994_AIF1DAC1_VU | 0xC0 /* 0dB */ + }, { + .mode = COMMON_SET_BIT, + .reg = WM8994_AIF1_DAC1_RIGHT_VOLUME, /* 403h */ + .mask = WM8994_AIF1DAC1R_VOL_MASK, + .gain = WM8994_AIF1DAC1_VU | 0xC0 /* 0dB */ + }, { + .mode = COMMON_SET_BIT, + .reg = WM8994_DAC2_LEFT_VOLUME, /* 612h */ + .mask = WM8994_DAC2L_VOL_MASK, + .gain = WM8994_DAC2_VU | 0xC0 /* 0dB */ + }, { + .mode = COMMON_SET_BIT, + .reg = WM8994_DAC2_RIGHT_VOLUME, /* 613h */ + .mask = WM8994_DAC2R_VOL_MASK, + .gain = WM8994_DAC2_VU | 0xC0 /* 0dB */ + }, { /* RCV */ + .mode = VOICECALL_RCV, + .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */ + .mask = WM8994_IN1L_VOL_MASK, + .gain = WM8994_IN1L_VU | 0x15 /* +15dB */ + }, { + .mode = VOICECALL_RCV, + .reg = WM8994_INPUT_MIXER_3, /* 29h */ + .mask = WM8994_IN1L_MIXINL_VOL_MASK | WM8994_MIXOUTL_MIXINL_VOL_MASK, + .gain = 0x10 /* +30dB */ + }, { + .mode = VOICECALL_RCV, + .reg = WM8994_OUTPUT_MIXER_5, /* 31h */ + .mask = WM8994_DACL_MIXOUTL_VOL_MASK, + .gain = 0x0 << WM8994_DACL_MIXOUTL_VOL_SHIFT + }, { + .mode = VOICECALL_RCV, + .reg = WM8994_OUTPUT_MIXER_6, /* 32h */ + .mask = WM8994_DACR_MIXOUTR_VOL_MASK, + .gain = 0x0 << WM8994_DACR_MIXOUTR_VOL_SHIFT + }, { + .mode = VOICECALL_RCV, + .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */ + .mask = WM8994_MIXOUTL_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x3F + }, { + .mode = VOICECALL_RCV, + .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */ + .mask = WM8994_MIXOUTR_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x3F + }, { + .mode = VOICECALL_RCV, + .reg = WM8994_HPOUT2_VOLUME, /* 1Fh */ + .mask = WM8994_HPOUT2_VOL_MASK, + .gain = 0x0 << WM8994_HPOUT2_VOL_SHIFT + }, { /* SPK */ + .mode = VOICECALL_SPK, + .reg = WM8994_INPUT_MIXER_3, /* 29h */ + .mask = WM8994_IN1L_MIXINL_VOL_MASK | WM8994_MIXOUTL_MIXINL_VOL_MASK, + .gain = 0x10 /* Mic +7.5dB */ + }, { + .mode = VOICECALL_SPK, + .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */ + .mask = WM8994_IN1L_VOL_MASK, + .gain = WM8994_IN1L_VU | 0x12 /* Mic +30dB */ + }, { + .mode = VOICECALL_SPK, + .reg = WM8994_SPKMIXL_ATTENUATION, /* 22h */ + .mask = WM8994_SPKMIXL_VOL_MASK, + .gain = 0x0 /* Speaker +0dB */ + }, { + .mode = VOICECALL_SPK, + .reg = WM8994_SPKMIXR_ATTENUATION, /* 23h */ + .mask = WM8994_SPKMIXR_VOL_MASK, + .gain = 0x0 /* Speaker +0dB */ + }, { + .mode = VOICECALL_SPK, + .reg = WM8994_SPEAKER_VOLUME_LEFT, /* 26h */ + .mask = WM8994_SPKOUTL_VOL_MASK, + .gain = WM8994_SPKOUT_VU | 0x3C /* Left Speaker +3dB */ + }, { + .mode = VOICECALL_SPK, + .reg = WM8994_SPEAKER_VOLUME_RIGHT, /* 27h */ + .mask = WM8994_SPKOUTR_VOL_MASK, /* Right Speaker -57dB */ + .gain = 0x0 + }, { + .mode = VOICECALL_SPK, + .reg = WM8994_CLASSD, /* 25h */ + .mask = WM8994_SPKOUTL_BOOST_MASK, + .gain = 0x7 << WM8994_SPKOUTL_BOOST_SHIFT /* Left spaker +12dB */ + }, { /* HP */ + .mode = VOICECALL_HP, + .reg = WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, /* 1Ah */ + .mask = WM8994_IN1R_VOL_MASK, + .gain = WM8994_IN1R_VU | 0x1D + }, { + .mode = VOICECALL_HP, + .reg = WM8994_INPUT_MIXER_4, /* 2Ah */ + .mask = WM8994_IN1R_MIXINR_VOL_MASK | WM8994_MIXOUTR_MIXINR_VOL_MASK, + .gain = 0x0 + }, { + .mode = VOICECALL_HP, + .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */ + .mask = WM8994_MIXOUTL_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x39 + }, { + .mode = VOICECALL_HP, + .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */ + .mask = WM8994_MIXOUTR_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x39 + }, { + .mode = VOICECALL_HP, + .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */ + .mask = WM8994_HPOUT1L_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x30 + }, { + .mode = VOICECALL_HP, + .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */ + .mask = WM8994_HPOUT1R_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x30 + }, { /* HP_NO_MIC */ + .mode = VOICECALL_HP_NO_MIC, + .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */ + .mask = WM8994_IN1L_VOL_MASK, + .gain = WM8994_IN1L_VU | 0x12 /* +10.5dB */ + }, { + .mode = VOICECALL_HP_NO_MIC, + .reg = WM8994_INPUT_MIXER_3, /* 29h */ + .mask = WM8994_IN1L_MIXINL_VOL_MASK | WM8994_MIXOUTL_MIXINL_VOL_MASK, + .gain = 0x10 + }, { + .mode = VOICECALL_HP_NO_MIC, + .reg = WM8994_LEFT_OPGA_VOLUME, /* 20h */ + .mask = WM8994_MIXOUTL_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x39 + }, { + .mode = VOICECALL_HP_NO_MIC, + .reg = WM8994_RIGHT_OPGA_VOLUME, /* 21h */ + .mask = WM8994_MIXOUTR_VOL_MASK, + .gain = WM8994_MIXOUT_VU | 0x39 + }, { + .mode = VOICECALL_HP_NO_MIC, + .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */ + .mask = WM8994_HPOUT1L_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x30 + }, { + .mode = VOICECALL_HP_NO_MIC, + .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */ + .mask = WM8994_HPOUT1R_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x30 + }, { /* TTY_VCO */ + .mode = VOICECALL_TTY_VCO, + .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */ + .mask = WM8994_IN1L_VOL_MASK, + .gain = WM8994_IN1L_VU | 0x15 /* +10.5dB */ + }, { + .mode = VOICECALL_TTY_VCO, + .reg = WM8994_INPUT_MIXER_3, /* 29h */ + .mask = WM8994_IN1L_MIXINL_VOL_MASK | WM8994_MIXOUTL_MIXINL_VOL_MASK, + .gain = 0x0 + }, { /* TTY_HCO */ + .mode = VOICECALL_TTY_HCO, + .reg = WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, /* 1Ah */ + .mask = WM8994_IN1R_VOL_MASK, + .gain = WM8994_IN1R_VU | 0x13 /* +12dB */ + }, { + .mode = VOICECALL_TTY_HCO, + .reg = WM8994_INPUT_MIXER_4, /* 2Ah */ + .mask = WM8994_IN1R_MIXINR_VOL_MASK | WM8994_MIXOUTR_MIXINR_VOL_MASK, + .gain = 0x0 + }, { /* TTY_FULL */ + .mode = VOICECALL_TTY_FULL, + .reg = WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, /* 1Ah */ + .mask = WM8994_IN1R_VOL_MASK, + .gain = WM8994_IN1R_VU | 0x13 /* +12dB */ + }, { + .mode = VOICECALL_TTY_FULL, + .reg = WM8994_INPUT_MIXER_4, /* 2Ah */ + .mask = WM8994_IN1R_MIXINR_VOL_MASK | WM8994_MIXOUTR_MIXINR_VOL_MASK, + .gain = 0x0 + }, +}; + +struct gain_info_t recording_gain_table[RECORDING_GAIN_NUM] = { + { /* MAIN */ + .mode = RECORDING_MAIN, + .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */ + .mask = WM8994_IN1L_VOL_MASK, + .gain = WM8994_IN1L_VU | 0x12 /* +10.5dB */ + }, { + .mode = RECORDING_MAIN, + .reg = WM8994_INPUT_MIXER_3, /* 29h */ + .mask = WM8994_IN1L_MIXINL_VOL_MASK | WM8994_MIXOUTL_MIXINL_VOL_MASK, + .gain = 0x10 /* +30dB */ + }, { + .mode = RECORDING_MAIN, + .reg = WM8994_AIF1_ADC1_LEFT_VOLUME, /* 400h */ + .mask = WM8994_AIF1ADC1L_VOL_MASK, + .gain = WM8994_AIF1ADC1_VU | 0xC0 /* 0dB */ + }, { + .mode = RECORDING_MAIN, + .reg = WM8994_AIF1_ADC1_RIGHT_VOLUME, /* 401h */ + .mask = WM8994_AIF1ADC1R_VOL_MASK, + .gain = WM8994_AIF1ADC1_VU | 0xC0 /* 0dB */ + }, { /* HP */ + .mode = RECORDING_HP, + .reg = WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, /* 1Ah */ + .mask = WM8994_IN1R_VOL_MASK, + .gain = WM8994_IN1R_VU | 0x15 + }, { + .mode = RECORDING_HP, + .reg = WM8994_INPUT_MIXER_4, /* 2Ah */ + .mask = WM8994_IN1R_MIXINR_VOL_MASK | WM8994_MIXOUTR_MIXINR_VOL_MASK, + .gain = 0x10 + }, { + .mode = RECORDING_HP, + .reg = WM8994_AIF1_ADC1_LEFT_VOLUME, /* 400h */ + .mask = WM8994_AIF1ADC1L_VOL_MASK, + .gain = WM8994_AIF1ADC1_VU | 0xC0 + }, { + .mode = RECORDING_HP, + .reg = WM8994_AIF1_ADC1_RIGHT_VOLUME, /* 401h */ + .mask = WM8994_AIF1ADC1R_VOL_MASK, + .gain = WM8994_AIF1ADC1_VU | 0xC0 + }, { /* RECOGNITION_MAIN */ + .mode = RECORDING_REC_MAIN, + .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */ + .mask = WM8994_IN1L_VOL_MASK, + .gain = WM8994_IN1L_VU | 0x0D /* +3dB */ + }, { + .mode = RECORDING_REC_MAIN, + .reg = WM8994_INPUT_MIXER_3, /* 29h */ + .mask = WM8994_IN1L_MIXINL_VOL_MASK | WM8994_MIXOUTL_MIXINL_VOL_MASK, + .gain = 0x10 /* 30dB */ + }, { + .mode = RECORDING_REC_MAIN, + .reg = WM8994_AIF1_ADC1_LEFT_VOLUME, /* 400h */ + .mask = WM8994_AIF1ADC1L_VOL_MASK, + .gain = WM8994_AIF1ADC1_VU | 0xc0 /* +0dB */ + }, { + .mode = RECORDING_REC_MAIN, + .reg = WM8994_AIF1_ADC1_RIGHT_VOLUME, /* 401h */ + .mask = WM8994_AIF1ADC1R_VOL_MASK, + .gain = WM8994_AIF1ADC1_VU | 0xc0 /* +0dB */ + }, { /* RECOGNITION_HP */ + .mode = RECORDING_REC_HP, + .reg = WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, /* 1Ah */ + .mask = WM8994_IN1R_VOL_MASK, + .gain = WM8994_IN1R_VU | 0x12 /* +10.5dB */ + }, { + .mode = RECORDING_REC_HP, + .reg = WM8994_INPUT_MIXER_4, /* 2Ah */ + .mask = WM8994_IN1R_MIXINR_VOL_MASK | WM8994_MIXOUTR_MIXINR_VOL_MASK, + .gain = 0x10 /* +30dB */ + }, { + .mode = RECORDING_REC_HP, + .reg = WM8994_AIF1_ADC1_LEFT_VOLUME, /* 400h */ + .mask = WM8994_AIF1ADC1L_VOL_MASK, + .gain = WM8994_AIF1ADC1_VU | 0xC0 + }, { + .mode = RECORDING_REC_HP, + .reg = WM8994_AIF1_ADC1_RIGHT_VOLUME, /* 401h */ + .mask = WM8994_AIF1ADC1R_VOL_MASK, + .gain = WM8994_AIF1ADC1_VU | 0xC0 + }, { /* CAMCORDER_MAIN */ + .mode = RECORDING_CAM_MAIN, + .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */ + .mask = WM8994_IN1L_VOL_MASK, + .gain = WM8994_IN1L_VU | 0x17 /* +18dB */ + }, { + .mode = RECORDING_CAM_MAIN, + .reg = WM8994_INPUT_MIXER_3, /* 29h */ + .mask = WM8994_IN1L_MIXINL_VOL_MASK | WM8994_MIXOUTL_MIXINL_VOL_MASK, + .gain = 0x10 /* 30dB */ + }, { + .mode = RECORDING_CAM_MAIN, + .reg = WM8994_AIF1_ADC1_LEFT_VOLUME, /* 400h */ + .mask = WM8994_AIF1ADC1L_VOL_MASK, + .gain = WM8994_AIF1ADC1_VU | 0xC0 /* +0dB */ + }, { + .mode = RECORDING_CAM_MAIN, + .reg = WM8994_AIF1_ADC1_RIGHT_VOLUME, /* 401h */ + .mask = WM8994_AIF1ADC1R_VOL_MASK, + .gain = WM8994_AIF1ADC1_VU | 0xC0 /* +0dB */ + }, { /* CAMCORDER_HP */ + .mode = RECORDING_CAM_HP, + .reg = WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, /* 1Ah */ + .mask = WM8994_IN1R_VOL_MASK, + .gain = WM8994_IN1R_VU | 0x15 /* +15dB */ + }, { + .mode = RECORDING_CAM_HP, + .reg = WM8994_INPUT_MIXER_4, /* 2Ah */ + .mask = WM8994_IN1R_MIXINR_VOL_MASK | WM8994_MIXOUTR_MIXINR_VOL_MASK, + .gain = 0x10 /* +30dB */ + }, { + .mode = RECORDING_CAM_HP, + .reg = WM8994_AIF1_ADC1_LEFT_VOLUME, /* 400h */ + .mask = WM8994_AIF1ADC1L_VOL_MASK, + .gain = WM8994_AIF1ADC1_VU | 0xC0 + }, { + .mode = RECORDING_CAM_HP, + .reg = WM8994_AIF1_ADC1_RIGHT_VOLUME, /* 401h */ + .mask = WM8994_AIF1ADC1R_VOL_MASK, + .gain = WM8994_AIF1ADC1_VU | 0xC0 + }, { /* VOICE COMMUNICATION MAIN */ + .mode = RECORDING_VC_MAIN, + .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */ + .mask = WM8994_IN1L_VOL_MASK, + .gain = WM8994_IN1L_VU | 0x12 /* +10.5dB */ + }, { + .mode = RECORDING_VC_MAIN, + .reg = WM8994_INPUT_MIXER_3, /* 29h */ + .mask = WM8994_IN1L_MIXINL_VOL_MASK | WM8994_MIXOUTL_MIXINL_VOL_MASK, + .gain = 0x10 /* +30dB */ + }, { + .mode = RECORDING_VC_MAIN, + .reg = WM8994_AIF1_ADC1_LEFT_VOLUME, /* 400h */ + .mask = WM8994_AIF1ADC1L_VOL_MASK, + .gain = WM8994_AIF1ADC1_VU | 0xC0 /* 0dB */ + }, { + .mode = RECORDING_VC_MAIN, + .reg = WM8994_AIF1_ADC1_RIGHT_VOLUME, /* 401h */ + .mask = WM8994_AIF1ADC1R_VOL_MASK, + .gain = WM8994_AIF1ADC1_VU | 0xC0 /* 0dB */ + }, { /* VOICE COMMUNICATION HP */ + .mode = RECORDING_VC_HP, + .reg = WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, /* 1Ah */ + .mask = WM8994_IN1R_VOL_MASK, + .gain = WM8994_IN1R_VU | 0x15 + }, { + .mode = RECORDING_VC_HP, + .reg = WM8994_INPUT_MIXER_4, /* 2Ah */ + .mask = WM8994_IN1R_MIXINR_VOL_MASK | WM8994_MIXOUTR_MIXINR_VOL_MASK, + .gain = 0x10 + }, { + .mode = RECORDING_VC_HP, + .reg = WM8994_AIF1_ADC1_LEFT_VOLUME, /* 400h */ + .mask = WM8994_AIF1ADC1L_VOL_MASK, + .gain = WM8994_AIF1ADC1_VU | 0xC0 + }, { + .mode = RECORDING_VC_HP, + .reg = WM8994_AIF1_ADC1_RIGHT_VOLUME, /* 401h */ + .mask = WM8994_AIF1ADC1R_VOL_MASK, + .gain = WM8994_AIF1ADC1_VU | 0xC0 + } +}; + +struct gain_info_t gain_code_table[GAIN_CODE_NUM] = { + /* Playback */ + {/* HP */ + .mode = PLAYBACK_HP | PLAYBACK_MODE | GAIN_DIVISION_BIT_1, + .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */ + .mask = WM8994_HPOUT1L_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x31 /* -8dB */ + }, { + .mode = PLAYBACK_HP | PLAYBACK_MODE | GAIN_DIVISION_BIT_1, + .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */ + .mask = WM8994_HPOUT1R_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x31 /* -8dB */ + }, {/* HP_NO_MIC */ + .mode = PLAYBACK_HP_NO_MIC | PLAYBACK_MODE | GAIN_DIVISION_BIT_1, + .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */ + .mask = WM8994_HPOUT1L_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x31 /* -8dB */ + }, { + .mode = PLAYBACK_HP_NO_MIC | PLAYBACK_MODE | GAIN_DIVISION_BIT_1, + .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */ + .mask = WM8994_HPOUT1R_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x31 /* -8dB */ + }, {/* Voicecall RCV */ + .mode = VOICECALL_RCV | VOICECALL_MODE | GAIN_DIVISION_BIT_1, + .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */ + .mask = WM8994_IN1L_VOL_MASK, + .gain = WM8994_IN1L_VU | 0x14 /* +13.5dB */ + }, {/* SPK */ + .mode = VOICECALL_SPK | VOICECALL_MODE | GAIN_DIVISION_BIT_1, + .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */ + .mask = WM8994_IN1L_VOL_MASK, + .gain = WM8994_IN1L_VU | 0x0D /* +3dB */ + }, { + .mode = VOICECALL_SPK | VOICECALL_MODE | GAIN_DIVISION_BIT_1, + .reg = WM8994_SPEAKER_VOLUME_LEFT, /* 26h */ + .mask = WM8994_SPKOUTL_VOL_MASK, + .gain = WM8994_SPKOUT_VU | 0x3A /* +1dB */ + }, {/* HP */ + .mode = VOICECALL_HP | VOICECALL_MODE | GAIN_DIVISION_BIT_1, + .reg = WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, /* 1Ah */ + .mask = WM8994_IN1R_VOL_MASK, + .gain = WM8994_IN1R_VU | 0x1D /* +27dB */ + }, { + .mode = VOICECALL_HP | VOICECALL_MODE | GAIN_DIVISION_BIT_1, + .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */ + .mask = WM8994_HPOUT1L_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x3a /* +1dB */ + }, { + .mode = VOICECALL_HP | VOICECALL_MODE | GAIN_DIVISION_BIT_1, + .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */ + .mask = WM8994_HPOUT1R_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x3a /* +1dB */ + }, {/* HP_NO_MIC */ + .mode = VOICECALL_HP_NO_MIC | VOICECALL_MODE | GAIN_DIVISION_BIT_1, + .reg = WM8994_LEFT_LINE_INPUT_1_2_VOLUME, /* 18h */ + .mask = WM8994_IN1L_VOL_MASK, + .gain = WM8994_IN1L_VU | 0x12 /* +10.5dB */ + }, { + .mode = VOICECALL_HP_NO_MIC | VOICECALL_MODE | GAIN_DIVISION_BIT_1, + .reg = WM8994_LEFT_OUTPUT_VOLUME, /* 1Ch */ + .mask = WM8994_HPOUT1L_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x3a /* +1dB */ + }, { + .mode = VOICECALL_HP_NO_MIC | VOICECALL_MODE | GAIN_DIVISION_BIT_1, + .reg = WM8994_RIGHT_OUTPUT_VOLUME, /* 1Dh */ + .mask = WM8994_HPOUT1R_VOL_MASK, + .gain = WM8994_HPOUT1_VU | 0x3a /* +1dB */ + }, +}; + +static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op) +{ + unsigned int reg; + int count = 0; + unsigned int val, start; + + val = op | WM8994_DCS_ENA_CHAN_0 | WM8994_DCS_ENA_CHAN_1; + + /* Trigger the command */ + snd_soc_write(codec, WM8994_DC_SERVO_1, val); + + start = jiffies; + pr_debug("Waiting for DC servo...\n"); + + do { + count++; + msleep(1); + reg = snd_soc_read(codec, WM8994_DC_SERVO_1); + pr_debug("DC servo: %x\n", reg); + } while (reg & op && count < 400); + + pr_info("DC servo took %dms\n", jiffies_to_msecs(jiffies - start)); + + if (reg & op) + pr_err("Timed out waiting for DC Servo\n"); +} + +/* S5P_SLEEP_CONFIG must be controlled by codec if codec use XUSBTI */ +int wm8994_configure_clock(struct snd_soc_codec *codec, int en) +{ + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + + if (en) { + clk_enable(wm8994->codec_clk); + DEBUG_LOG("USBOSC Enabled in Sleep Mode\n"); + } else { + clk_disable(wm8994->codec_clk); + DEBUG_LOG("USBOSC disable in Sleep Mode\n"); + } + + return 0; +} + +void audio_ctrl_mic_bias_gpio(struct wm8994_platform_data *pdata, int enable) +{ + DEBUG_LOG("enable = [%d]", enable); + + if (!pdata) + pr_err("failed to turn off micbias pin\n"); + else { + if (enable) + pdata->set_mic_bias(true); + else + pdata->set_mic_bias(false); + } +} + +static int wm8994_earsel_control(struct wm8994_platform_data *pdata, int en) +{ + + if (!pdata) { + pr_err("failed to control wm8994 ear selection\n"); + return -EINVAL; + } + + gpio_set_value(pdata->ear_sel, en); + + return 0; + +} + +/* Audio Routing routines for the universal board..wm8994 codec*/ +void wm8994_disable_path(struct snd_soc_codec *codec) +{ + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + + u16 val; + enum audio_path path = wm8994->cur_path; + + DEBUG_LOG("Path = [%d]", path); + + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1); + + switch (path) { + case RCV: + /* Disbale the HPOUT2 */ + val &= ~(WM8994_HPOUT2_ENA_MASK); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val); + + /* Disable left MIXOUT */ + val = wm8994_read(codec, WM8994_OUTPUT_MIXER_1); + val &= ~(WM8994_DAC1L_TO_MIXOUTL_MASK); + wm8994_write(codec, WM8994_OUTPUT_MIXER_1, val); + + /* Disable right MIXOUT */ + val = wm8994_read(codec, WM8994_OUTPUT_MIXER_2); + val &= ~(WM8994_DAC1R_TO_MIXOUTR_MASK); + wm8994_write(codec, WM8994_OUTPUT_MIXER_2, val); + + /* Disable HPOUT Mixer */ + val = wm8994_read(codec, WM8994_HPOUT2_MIXER); + val &= ~(WM8994_MIXOUTLVOL_TO_HPOUT2_MASK | + WM8994_MIXOUTRVOL_TO_HPOUT2_MASK); + wm8994_write(codec, WM8994_HPOUT2_MIXER, val); + + /* Disable mixout volume control */ + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_3); + val &= ~(WM8994_MIXOUTLVOL_ENA_MASK | + WM8994_MIXOUTRVOL_ENA_MASK | + WM8994_MIXOUTL_ENA_MASK | + WM8994_MIXOUTR_ENA_MASK); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, val); + break; + + case SPK: + /* Disbale the SPKOUTL */ + val &= ~(WM8994_SPKOUTL_ENA_MASK); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val); + + /* Disable SPKLVOL */ + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_3); + val &= ~(WM8994_SPKLVOL_ENA_MASK); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, val); + + /* Disable SPKOUT mixer */ + val = wm8994_read(codec, WM8994_SPKOUT_MIXERS); + val &= ~(WM8994_SPKMIXL_TO_SPKOUTL_MASK | + WM8994_SPKMIXR_TO_SPKOUTL_MASK | + WM8994_SPKMIXR_TO_SPKOUTR_MASK); + wm8994_write(codec, WM8994_SPKOUT_MIXERS, val); + + /* Mute Speaker mixer */ + val = wm8994_read(codec, WM8994_SPEAKER_MIXER); + val &= ~(WM8994_DAC1L_TO_SPKMIXL_MASK); + wm8994_write(codec, WM8994_SPEAKER_MIXER, val); + break; + + case HP: + case HP_NO_MIC: + val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME); + val &= ~(0x02C0); + val |= 0x02C0; + wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, 0x02C0); + + val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME); + val &= ~(0x02C0); + val |= 0x02C0; + wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, 0x02C0); + + val = wm8994_read(codec, WM8994_ANALOGUE_HP_1); + val &= ~(0x0022); + val |= 0x0022; + wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x0022); + + val = wm8994_read(codec, WM8994_OUTPUT_MIXER_1); + val &= ~(0x0); + val |= 0x0; + wm8994_write(codec, WM8994_OUTPUT_MIXER_1, 0x0); + + val = wm8994_read(codec, WM8994_OUTPUT_MIXER_2); + val &= ~(0x0); + val |= 0x0; + wm8994_write(codec, WM8994_OUTPUT_MIXER_2, 0x0); + + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_5); + val &= ~(0x0300); + val |= 0x0300; + wm8994_write(codec, WM8994_POWER_MANAGEMENT_5, 0x0300); + + val = wm8994_read(codec, WM8994_CHARGE_PUMP_1); + val &= ~(0x1F25); + val |= 0x1F25; + wm8994_write(codec, WM8994_CHARGE_PUMP_1, 0x1F25); + break; + + case BT: + val = wm8994_read(codec, WM8994_AIF1_DAC1_FILTERS_1); + val &= ~(WM8994_AIF1DAC1_MUTE_MASK | WM8994_AIF1DAC1_MONO_MASK); + val |= (WM8994_AIF1DAC1_MUTE); + wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, val); + break; + + case SPK_HP: + val &= ~(WM8994_HPOUT1L_ENA_MASK | WM8994_HPOUT1R_ENA_MASK | + WM8994_SPKOUTL_ENA_MASK); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val); + + /* Disable DAC1L to HPOUT1L path */ + val = wm8994_read(codec, WM8994_OUTPUT_MIXER_1); + val &= ~(WM8994_DAC1L_TO_HPOUT1L_MASK | + WM8994_DAC1L_TO_MIXOUTL_MASK); + wm8994_write(codec, WM8994_OUTPUT_MIXER_1, val); + + /* Disable DAC1R to HPOUT1R path */ + val = wm8994_read(codec, WM8994_OUTPUT_MIXER_2); + val &= ~(WM8994_DAC1R_TO_HPOUT1R_MASK | + WM8994_DAC1R_TO_MIXOUTR_MASK); + wm8994_write(codec, WM8994_OUTPUT_MIXER_2, val); + + /* Disable Charge Pump */ + val = wm8994_read(codec, WM8994_CHARGE_PUMP_1); + val &= ~WM8994_CP_ENA_MASK; + val |= WM8994_CP_ENA_DEFAULT; + wm8994_write(codec, WM8994_CHARGE_PUMP_1, val); + + /* Intermediate HP settings */ + val = wm8994_read(codec, WM8994_ANALOGUE_HP_1); + val &= ~(WM8994_HPOUT1R_DLY_MASK | WM8994_HPOUT1R_OUTP_MASK | + WM8994_HPOUT1R_RMV_SHORT_MASK | WM8994_HPOUT1L_DLY_MASK | + WM8994_HPOUT1L_OUTP_MASK | WM8994_HPOUT1L_RMV_SHORT_MASK); + wm8994_write(codec, WM8994_ANALOGUE_HP_1, val); + + /* Disable SPKLVOL */ + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_3); + val &= ~(WM8994_SPKLVOL_ENA_MASK); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, val); + + /* Disable SPKOUT mixer */ + val = wm8994_read(codec, WM8994_SPKOUT_MIXERS); + val &= ~(WM8994_SPKMIXL_TO_SPKOUTL_MASK | + WM8994_SPKMIXR_TO_SPKOUTL_MASK | + WM8994_SPKMIXR_TO_SPKOUTR_MASK); + wm8994_write(codec, WM8994_SPKOUT_MIXERS, val); + + /* Mute Speaker mixer */ + val = wm8994_read(codec, WM8994_SPEAKER_MIXER); + val &= ~(WM8994_DAC1L_TO_SPKMIXL_MASK); + wm8994_write(codec, WM8994_SPEAKER_MIXER, val); + break; + + default: + DEBUG_LOG_ERR("Path[%d] is not invaild!\n", path); + return; + break; + } +} + +void wm8994_disable_rec_path(struct snd_soc_codec *codec) +{ + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + + u16 val; + enum mic_path mic = wm8994->rec_path; + + wm8994->rec_path = MIC_OFF; + + if (!(wm8994->codec_state & CALL_ACTIVE)) + audio_ctrl_mic_bias_gpio(wm8994->pdata, 0); + + switch (mic) { + case MAIN: + DEBUG_LOG("Disabling MAIN Mic Path..\n"); + + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_2); + val &= ~(WM8994_IN1L_ENA_MASK | WM8994_MIXINL_ENA_MASK); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, val); + + /* Mute IN1L PGA, update volume */ + val = wm8994_read(codec, + WM8994_LEFT_LINE_INPUT_1_2_VOLUME); + val &= ~(WM8994_IN1L_MUTE_MASK | WM8994_IN1L_VOL_MASK); + val |= (WM8994_IN1L_VU | WM8994_IN1L_MUTE); + wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME, + val); + + /*Mute the PGA */ + val = wm8994_read(codec, WM8994_INPUT_MIXER_3); + val &= ~(WM8994_IN1L_TO_MIXINL_MASK | + WM8994_IN1L_MIXINL_VOL_MASK | + WM8994_MIXOUTL_MIXINL_VOL_MASK); + wm8994_write(codec, WM8994_INPUT_MIXER_3, val); + + /* Disconnect IN1LN ans IN1LP to the inputs */ + val = wm8994_read(codec, WM8994_INPUT_MIXER_2); + val &= (WM8994_IN1LN_TO_IN1L_MASK | WM8994_IN1LP_TO_IN1L_MASK); + wm8994_write(codec, WM8994_INPUT_MIXER_2, val); + + /* Digital Paths */ + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_4); + val &= ~(WM8994_ADCL_ENA_MASK | WM8994_AIF1ADC1L_ENA_MASK); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_4, val); + + /* Disable timeslots */ + val = wm8994_read(codec, WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING); + val &= ~(WM8994_ADC1L_TO_AIF1ADC1L); + wm8994_write(codec, WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING, val); + break; + + case SUB: + DEBUG_LOG("Disbaling SUB Mic path..\n"); + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_2); + val &= ~(WM8994_IN1R_ENA_MASK | WM8994_MIXINR_ENA_MASK); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, val); + + /* Disable volume,unmute Right Line */ + val = wm8994_read(codec, + WM8994_RIGHT_LINE_INPUT_1_2_VOLUME); + val &= ~WM8994_IN1R_MUTE_MASK; /* Unmute IN1R */ + val |= (WM8994_IN1R_VU | WM8994_IN1R_MUTE); + wm8994_write(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, + val); + + /* Mute right pga, set volume */ + val = wm8994_read(codec, WM8994_INPUT_MIXER_4); + val &= ~(WM8994_IN1R_TO_MIXINR_MASK | + WM8994_IN1R_MIXINR_VOL_MASK | + WM8994_MIXOUTR_MIXINR_VOL_MASK); + wm8994_write(codec, WM8994_INPUT_MIXER_4, val); + + /* Disconnect in1rn to inr1 and in1rp to inrp */ + val = wm8994_read(codec, WM8994_INPUT_MIXER_2); + val &= ~(WM8994_IN1RN_TO_IN1R_MASK | WM8994_IN1RP_TO_IN1R_MASK); + wm8994_write(codec, WM8994_INPUT_MIXER_2, val); + + /* Digital Paths */ + /* Disable right ADC and time slot */ + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_4); + val &= ~(WM8994_ADCR_ENA_MASK | WM8994_AIF1ADC1R_ENA_MASK); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_4, val); + + /* ADC Right mixer routing */ + val = wm8994_read(codec, WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING); + val &= ~(WM8994_ADC1R_TO_AIF1ADC1R_MASK); + wm8994_write(codec, WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING, val); + break; + + case BT_REC: + DEBUG_LOG("Disbaling BT Mic path..\n"); + val = wm8994_read(codec, WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING); + val &= ~(WM8994_AIF2DACL_TO_AIF1ADC1L_MASK | + WM8994_ADC1L_TO_AIF1ADC1L_MASK); + wm8994_write(codec, WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING, val); + + val = wm8994_read(codec, WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING); + val &= ~(WM8994_AIF2DACR_TO_AIF1ADC1R_MASK | + WM8994_ADC1R_TO_AIF1ADC1R_MASK); + wm8994_write(codec, WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING, val); + + val = wm8994_read(codec, WM8994_AIF2_DAC_FILTERS_1); + val &= ~(WM8994_AIF2DAC_MUTE_MASK); + val |= (WM8994_AIF2DAC_MUTE); + wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, val); + break; + + case MIC_OFF: + DEBUG_LOG("Mic is already OFF!\n"); + break; + + default: + DEBUG_LOG_ERR("Path[%d] is not invaild!\n", mic); + break; + } +} + +void wm8994_set_bluetooth_common_setting(struct snd_soc_codec *codec) +{ + u32 val; + + wm8994_write(codec, WM8994_GPIO_1, 0xA101); + wm8994_write(codec, WM8994_GPIO_2, 0x8100); + wm8994_write(codec, WM8994_GPIO_3, 0x0100); + wm8994_write(codec, WM8994_GPIO_4, 0x0100); + wm8994_write(codec, WM8994_GPIO_5, 0x8100); + wm8994_write(codec, WM8994_GPIO_6, 0xA101); + wm8994_write(codec, WM8994_GPIO_7, 0x0100); + wm8994_write(codec, WM8994_GPIO_8, 0xA101); + wm8994_write(codec, WM8994_GPIO_9, 0xA101); + wm8994_write(codec, WM8994_GPIO_10, 0xA101); + wm8994_write(codec, WM8994_GPIO_11, 0xA101); + + wm8994_write(codec, WM8994_FLL2_CONTROL_2, 0x0700); + wm8994_write(codec, WM8994_FLL2_CONTROL_3, 0x3126); + wm8994_write(codec, WM8994_FLL2_CONTROL_4, 0x0100); + wm8994_write(codec, WM8994_FLL2_CONTROL_5, 0x0C88); + wm8994_write(codec, WM8994_FLL2_CONTROL_1, + WM8994_FLL2_FRACN_ENA | WM8994_FLL2_ENA); + + val = wm8994_read(codec, WM8994_AIF2_CLOCKING_1); + if (!(val & WM8994_AIF2CLK_ENA)) + wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0018); + + wm8994_write(codec, WM8994_AIF2_RATE, 0x9 << WM8994_AIF2CLK_RATE_SHIFT); + + /* AIF2 Interface - PCM Stereo mode */ + /* Left Justified, BCLK invert, LRCLK Invert */ + wm8994_write(codec, WM8994_AIF2_CONTROL_1, + WM8994_AIF2ADCR_SRC | WM8994_AIF2_BCLK_INV | 0x18); + + wm8994_write(codec, WM8994_AIF2_BCLK, 0x70); + wm8994_write(codec, WM8994_AIF2_CONTROL_2, 0x0000); + wm8994_write(codec, WM8994_AIF2_MASTER_SLAVE, WM8994_AIF2_MSTR | + WM8994_AIF2_CLK_FRC | WM8994_AIF2_LRCLK_FRC); + + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_5); + val &= ~(WM8994_AIF2DACL_ENA_MASK | WM8994_AIF2DACR_ENA_MASK | + WM8994_AIF1DAC1L_ENA_MASK | WM8994_AIF1DAC1R_ENA_MASK | + WM8994_DAC1L_ENA_MASK | WM8994_DAC1R_ENA_MASK); + val |= (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA | + WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA | + WM8994_DAC1L_ENA | WM8994_DAC1R_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_5, val); + + /* Clocking */ + val = wm8994_read(codec, WM8994_CLOCKING_1); + val |= (WM8994_DSP_FS2CLK_ENA | WM8994_SYSCLK_SRC); + wm8994_write(codec, WM8994_CLOCKING_1, val); + + /* AIF1 & AIF2 Output is connected to DAC1 */ + val = wm8994_read(codec, WM8994_DAC1_LEFT_MIXER_ROUTING); + val &= ~(WM8994_AIF1DAC1L_TO_DAC1L_MASK | + WM8994_AIF2DACL_TO_DAC1L_MASK); + val |= (WM8994_AIF1DAC1L_TO_DAC1L | WM8994_AIF2DACL_TO_DAC1L); + wm8994_write(codec, WM8994_DAC1_LEFT_MIXER_ROUTING, val); + + val = wm8994_read(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING); + val &= ~(WM8994_AIF1DAC1R_TO_DAC1R_MASK | + WM8994_AIF2DACR_TO_DAC1R_MASK); + val |= (WM8994_AIF1DAC1R_TO_DAC1R | WM8994_AIF2DACR_TO_DAC1R); + wm8994_write(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING, val); +} + +void wm8994_record_headset_mic(struct snd_soc_codec *codec) +{ + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + + u16 val; + + DEBUG_LOG("Recording through Headset Mic\n"); + + wm8994_write(codec, WM8994_ANTIPOP_2, 0x68); + + /* Enable high pass filter to control bounce on startup */ + val = wm8994_read(codec, WM8994_AIF1_ADC1_FILTERS); + val &= ~(WM8994_AIF1ADC1L_HPF_MASK | WM8994_AIF1ADC1R_HPF_MASK); + val |= (WM8994_AIF1ADC1R_HPF); + wm8994_write(codec, WM8994_AIF1_ADC1_FILTERS, val); + + /* Enable mic bias, vmid, bias generator */ + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1); + val &= ~(WM8994_BIAS_ENA_MASK | WM8994_VMID_SEL_MASK); + val |= (WM8994_BIAS_ENA | WM8994_VMID_SEL_NORMAL); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val); + + val = wm8994_read(codec, WM8994_INPUT_MIXER_1); + val &= ~(WM8994_INPUTS_CLAMP_MASK); + val |= (WM8994_INPUTS_CLAMP); + wm8994_write(codec, WM8994_INPUT_MIXER_1, val); + + val = (WM8994_MIXINR_ENA | WM8994_IN1R_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, val); + + + val = (WM8994_IN1RN_TO_IN1R | WM8994_IN1RP_TO_IN1R); + wm8994_write(codec, WM8994_INPUT_MIXER_2, val); + + val = wm8994_read(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME); + val &= ~(WM8994_IN1R_MUTE_MASK); + wm8994_write(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, val); + + val = wm8994_read(codec, WM8994_INPUT_MIXER_4); + val &= ~(WM8994_IN1R_TO_MIXINR_MASK); + val |= (WM8994_IN1R_TO_MIXINR); + wm8994_write(codec, WM8994_INPUT_MIXER_4 , val); + + val = wm8994_read(codec, WM8994_INPUT_MIXER_1); + val &= ~(WM8994_INPUTS_CLAMP_MASK); + wm8994_write(codec, WM8994_INPUT_MIXER_1, val); + + val = wm8994_read(codec, WM8994_AIF1_ADC1_RIGHT_VOLUME); + val |= (WM8994_AIF1ADC1_VU); + wm8994_write(codec, WM8994_AIF1_ADC1_RIGHT_VOLUME, val); + + val = wm8994_read(codec, WM8994_AIF1_ADC1_FILTERS); + val &= ~(WM8994_AIF1ADC1L_HPF_MASK | WM8994_AIF1ADC1R_HPF_MASK); + val |= (WM8994_AIF1ADC1R_HPF | 0x2000); + wm8994_write(codec, WM8994_AIF1_ADC1_FILTERS, val); + + val = wm8994_read(codec, WM8994_AIF1_MASTER_SLAVE); + val |= (WM8994_AIF1_MSTR | WM8994_AIF1_CLK_FRC | WM8994_AIF1_LRCLK_FRC); + wm8994_write(codec, WM8994_AIF1_MASTER_SLAVE, val); + + wm8994_write(codec, WM8994_GPIO_1, 0xA101); + + /* Mixing left channel output to right channel */ + val = wm8994_read(codec, WM8994_AIF1_CONTROL_1); + val &= ~(WM8994_AIF1ADCL_SRC_MASK | WM8994_AIF1ADCR_SRC_MASK); + val |= (WM8994_AIF1ADCL_SRC | WM8994_AIF1ADCR_SRC); + wm8994_write(codec, WM8994_AIF1_CONTROL_1, val); + + /* Digital Paths */ + /* Enable right ADC and time slot */ + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_4); + val &= ~(WM8994_ADCR_ENA_MASK | WM8994_AIF1ADC1R_ENA_MASK); + val |= (WM8994_AIF1ADC1R_ENA | WM8994_ADCR_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_4, val); + + + /* ADC Right mixer routing */ + val = wm8994_read(codec, WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING); + val &= ~(WM8994_ADC1R_TO_AIF1ADC1R_MASK); + val |= WM8994_ADC1R_TO_AIF1ADC1R; + wm8994_write(codec, WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING, val); + + val = wm8994_read(codec, WM8994_SPEAKER_MIXER); + val &= ~WM8994_MIXINL_TO_SPKMIXL_MASK; + wm8994_write(codec, WM8994_SPEAKER_MIXER, val); + + val = wm8994_read(codec, WM8994_OUTPUT_MIXER_1); + val &= ~WM8994_MIXINL_TO_MIXOUTL_MASK; + wm8994_write(codec, WM8994_OUTPUT_MIXER_1, val); + + val = wm8994_read(codec, WM8994_OUTPUT_MIXER_2); + val &= ~WM8994_MIXINR_TO_MIXOUTR_MASK; + wm8994_write(codec, WM8994_OUTPUT_MIXER_2, val); + + val = wm8994_read(codec, WM8994_DAC2_LEFT_MIXER_ROUTING); + val &= ~(WM8994_ADC1_TO_DAC2L_MASK); + wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING, val); + + val = wm8994_read(codec, WM8994_DAC2_RIGHT_MIXER_ROUTING); + val &= ~(WM8994_ADC1_TO_DAC2R_MASK); + wm8994_write(codec, WM8994_DAC2_RIGHT_MIXER_ROUTING, val); + + if (wm8994->input_source == RECOGNITION) + wm8994_set_codec_gain(codec, RECORDING_MODE, RECORDING_REC_HP); + else if (wm8994->input_source == CAMCORDER) + wm8994_set_codec_gain(codec, RECORDING_MODE, RECORDING_CAM_HP); + else if (wm8994->input_source == VOICE_COMMUNICATION) + wm8994_set_codec_gain(codec, RECORDING_MODE, RECORDING_VC_HP); + else + wm8994_set_codec_gain(codec, RECORDING_MODE, RECORDING_HP); + +} + +void wm8994_record_main_mic(struct snd_soc_codec *codec) +{ + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + + u16 val; + + DEBUG_LOG("Recording through Main Mic\n"); + audio_ctrl_mic_bias_gpio(wm8994->pdata, 1); + + /* Main mic volume issue fix: requested H/W */ + wm8994_write(codec, WM8994_ANTIPOP_2, 0x68); + + /* High pass filter to control bounce on enable */ + val = wm8994_read(codec, WM8994_AIF1_ADC1_FILTERS); + val &= ~(WM8994_AIF1ADC1L_HPF_MASK | WM8994_AIF1ADC1R_HPF_MASK); + val |= (WM8994_AIF1ADC1L_HPF); + wm8994_write(codec, WM8994_AIF1_ADC1_FILTERS, val); + + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1); + val &= ~(WM8994_BIAS_ENA_MASK | WM8994_VMID_SEL_MASK); + val |= (WM8994_BIAS_ENA | WM8994_VMID_SEL_NORMAL); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val); + + val = wm8994_read(codec, WM8994_INPUT_MIXER_1); + val &= ~(WM8994_INPUTS_CLAMP_MASK); + val |= (WM8994_INPUTS_CLAMP); + wm8994_write(codec, WM8994_INPUT_MIXER_1, val); + + val = (WM8994_MIXINL_ENA | WM8994_IN1L_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, val); + + val = (WM8994_IN1LP_TO_IN1L | WM8994_IN1LN_TO_IN1L); + wm8994_write(codec, WM8994_INPUT_MIXER_2, val); + + + val = wm8994_read(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME); + val &= ~(WM8994_IN1L_MUTE_MASK); + wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME, val); + + val = wm8994_read(codec, WM8994_INPUT_MIXER_3); + val &= ~(WM8994_IN1L_TO_MIXINL_MASK); + val |= (WM8994_IN1L_TO_MIXINL); + wm8994_write(codec, WM8994_INPUT_MIXER_3, val); + + val = wm8994_read(codec, WM8994_INPUT_MIXER_1); + val &= ~(WM8994_INPUTS_CLAMP_MASK); + wm8994_write(codec, WM8994_INPUT_MIXER_1, val); + + + val = wm8994_read(codec, WM8994_AIF1_ADC1_LEFT_VOLUME); + val |= (WM8994_AIF1ADC1_VU); + wm8994_write(codec, WM8994_AIF1_ADC1_LEFT_VOLUME, val); + + val = wm8994_read(codec, WM8994_AIF1_ADC1_FILTERS); + val &= ~(WM8994_AIF1ADC1L_HPF_MASK | WM8994_AIF1ADC1R_HPF_MASK); + val |= (WM8994_AIF1ADC1L_HPF | 0x2000); + wm8994_write(codec, WM8994_AIF1_ADC1_FILTERS, val); + + val = wm8994_read(codec, WM8994_AIF1_MASTER_SLAVE); + val |= (WM8994_AIF1_MSTR | WM8994_AIF1_CLK_FRC | WM8994_AIF1_LRCLK_FRC); + wm8994_write(codec, WM8994_AIF1_MASTER_SLAVE, val); + + wm8994_write(codec, WM8994_GPIO_1, 0xA101); + + val = wm8994_read(codec, WM8994_AIF1_CONTROL_1); + val &= ~(WM8994_AIF1ADCL_SRC_MASK | WM8994_AIF1ADCR_SRC_MASK); + val |= (WM8994_AIF1ADCR_SRC); + wm8994_write(codec, WM8994_AIF1_CONTROL_1, val); + + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_4); + val &= ~(WM8994_ADCL_ENA_MASK | WM8994_AIF1ADC1L_ENA_MASK); + val |= (WM8994_AIF1ADC1L_ENA | WM8994_ADCL_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_4, val); + + /* Enable timeslots */ + val = wm8994_read(codec, WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING); + val |= WM8994_ADC1L_TO_AIF1ADC1L; + wm8994_write(codec, WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING, val); + + val = wm8994_read(codec, WM8994_SPEAKER_MIXER); + val &= ~WM8994_MIXINL_TO_SPKMIXL_MASK; + wm8994_write(codec, WM8994_SPEAKER_MIXER, val); + + val = wm8994_read(codec, WM8994_OUTPUT_MIXER_1); + val &= ~WM8994_MIXINL_TO_MIXOUTL_MASK; + wm8994_write(codec, WM8994_OUTPUT_MIXER_1, val); + + val = wm8994_read(codec, WM8994_OUTPUT_MIXER_2); + val &= ~WM8994_MIXINR_TO_MIXOUTR_MASK; + wm8994_write(codec, WM8994_OUTPUT_MIXER_2, val); + + val = wm8994_read(codec, WM8994_DAC2_LEFT_MIXER_ROUTING); + val &= ~(WM8994_ADC1_TO_DAC2L_MASK); + wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING, val); + + val = wm8994_read(codec, WM8994_DAC2_RIGHT_MIXER_ROUTING); + val &= ~(WM8994_ADC1_TO_DAC2R_MASK); + wm8994_write(codec, WM8994_DAC2_RIGHT_MIXER_ROUTING, val); + + if (wm8994->input_source == RECOGNITION) + wm8994_set_codec_gain(codec, RECORDING_MODE, + RECORDING_REC_MAIN); + else if (wm8994->input_source == CAMCORDER) + wm8994_set_codec_gain(codec, RECORDING_MODE, + RECORDING_CAM_MAIN); + else if (wm8994->input_source == VOICE_COMMUNICATION) + wm8994_set_codec_gain(codec, RECORDING_MODE, + RECORDING_VC_MAIN); + else + wm8994_set_codec_gain(codec, RECORDING_MODE, RECORDING_MAIN); + +} + +void wm8994_record_bluetooth(struct snd_soc_codec *codec) +{ + u16 val; + + DEBUG_LOG("BT Record Path for Voice Command\n"); + + wm8994_set_bluetooth_common_setting(codec); + + val = wm8994_read(codec, WM8994_DAC2_LEFT_MIXER_ROUTING); + val &= ~(WM8994_ADC1_TO_DAC2L_MASK); + wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING, val); + + val = wm8994_read(codec, WM8994_DAC2_RIGHT_MIXER_ROUTING); + val &= ~(WM8994_ADC1_TO_DAC2R_MASK); + wm8994_write(codec, WM8994_DAC2_RIGHT_MIXER_ROUTING, val); + + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1); + val &= ~(WM8994_BIAS_ENA_MASK | WM8994_VMID_SEL_MASK); + val |= (WM8994_BIAS_ENA | WM8994_VMID_SEL_NORMAL); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val); + + wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, 0x0000); + + wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, 0x0000); + + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_4); + val &= ~(WM8994_AIF1ADC1L_ENA_MASK | WM8994_AIF1ADC1R_ENA_MASK); + val |= (WM8994_AIF1ADC1L_ENA | WM8994_AIF1ADC1R_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_4 , val); + + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_5); + val &= ~(WM8994_AIF2DACL_ENA_MASK | WM8994_AIF2DACR_ENA_MASK); + val |= (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_5, val); + + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_6); + val &= ~(WM8994_AIF3_ADCDAT_SRC_MASK | WM8994_AIF2_DACDAT_SRC_MASK); + val |= (0x1 << WM8994_AIF3_ADCDAT_SRC_SHIFT | WM8994_AIF2_DACDAT_SRC); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_6, val); + + val = wm8994_read(codec, WM8994_AIF2_DAC_FILTERS_1); + val &= ~(WM8994_AIF2DAC_MUTE_MASK); + wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, val); + + val = wm8994_read(codec, WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING); + val &= ~(WM8994_AIF2DACL_TO_AIF1ADC1L_MASK); + val |= (WM8994_AIF2DACL_TO_AIF1ADC1L); + wm8994_write(codec, WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING, val); + + val = wm8994_read(codec, WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING); + val &= ~(WM8994_AIF2DACR_TO_AIF1ADC1R_MASK); + val |= (WM8994_AIF2DACR_TO_AIF1ADC1R); + wm8994_write(codec, WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING, val); + + wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019); + + wm8994_write(codec, WM8994_OVERSAMPLING, 0X0000); + + wm8994_write(codec, WM8994_GPIO_8, WM8994_GP8_DIR | WM8994_GP8_DB); + wm8994_write(codec, WM8994_GPIO_9, WM8994_GP9_DB); + wm8994_write(codec, WM8994_GPIO_10, WM8994_GP10_DB); + wm8994_write(codec, WM8994_GPIO_11, WM8994_GP11_DB); +} +void wm8994_set_playback_receiver(struct snd_soc_codec *codec) +{ + u16 val; + + DEBUG_LOG(""); + + val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME); + val &= ~(WM8994_MIXOUTL_MUTE_N_MASK); + val |= (WM8994_MIXOUTL_MUTE_N); + wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, val); + + val = wm8994_read(codec, WM8994_RIGHT_OPGA_VOLUME); + val &= ~(WM8994_MIXOUTR_MUTE_N_MASK); + val |= (WM8994_MIXOUTR_MUTE_N); + wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val); + + val = wm8994_read(codec, WM8994_HPOUT2_VOLUME); + val &= ~(WM8994_HPOUT2_MUTE_MASK); + wm8994_write(codec, WM8994_HPOUT2_VOLUME, val); + + /* Unmute DAC1 left */ + val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME); + val &= ~(WM8994_DAC1L_MUTE_MASK); + wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val); + + /* Unmute and volume ctrl RightDAC */ + val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME); + val &= ~(WM8994_DAC1R_MUTE_MASK); + wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val); + + val = wm8994_read(codec, WM8994_OUTPUT_MIXER_1); + val &= ~(WM8994_DAC1L_TO_MIXOUTL_MASK); + val |= (WM8994_DAC1L_TO_MIXOUTL); + wm8994_write(codec, WM8994_OUTPUT_MIXER_1, val); + + val = wm8994_read(codec, WM8994_OUTPUT_MIXER_2); + val &= ~(WM8994_DAC1R_TO_MIXOUTR_MASK); + val |= (WM8994_DAC1R_TO_MIXOUTR); + wm8994_write(codec, WM8994_OUTPUT_MIXER_2, val); + + val = wm8994_read(codec, WM8994_HPOUT2_MIXER); + val &= ~(WM8994_MIXOUTLVOL_TO_HPOUT2_MASK | + WM8994_MIXOUTRVOL_TO_HPOUT2_MASK); + val |= (WM8994_MIXOUTRVOL_TO_HPOUT2 | WM8994_MIXOUTLVOL_TO_HPOUT2); + wm8994_write(codec, WM8994_HPOUT2_MIXER, val); + + wm8994_set_codec_gain(codec, PLAYBACK_MODE, PLAYBACK_RCV); + + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_5); + val &= ~(WM8994_DAC1R_ENA_MASK | WM8994_DAC1L_ENA_MASK | + WM8994_AIF1DAC1R_ENA_MASK | WM8994_AIF1DAC1L_ENA_MASK); + val |= (WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA | + WM8994_DAC1L_ENA | WM8994_DAC1R_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_5, val); + + val = wm8994_read(codec, WM8994_DAC1_LEFT_MIXER_ROUTING); + val &= ~(WM8994_AIF1DAC1L_TO_DAC1L_MASK); + val |= (WM8994_AIF1DAC1L_TO_DAC1L); + wm8994_write(codec, WM8994_DAC1_LEFT_MIXER_ROUTING, val); + + val = wm8994_read(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING); + val &= ~(WM8994_AIF1DAC1R_TO_DAC1R_MASK); + val |= (WM8994_AIF1DAC1R_TO_DAC1R); + wm8994_write(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING, val); + + val = wm8994_read(codec, WM8994_CLOCKING_1); + val &= ~(WM8994_DSP_FS1CLK_ENA_MASK | WM8994_DSP_FSINTCLK_ENA_MASK); + val |= (WM8994_DSP_FS1CLK_ENA | WM8994_DSP_FSINTCLK_ENA); + wm8994_write(codec, WM8994_CLOCKING_1, val); + + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_3); + val &= ~(WM8994_MIXOUTLVOL_ENA_MASK | WM8994_MIXOUTRVOL_ENA_MASK | + WM8994_MIXOUTL_ENA_MASK | WM8994_MIXOUTR_ENA_MASK); + val |= (WM8994_MIXOUTL_ENA | WM8994_MIXOUTR_ENA | + WM8994_MIXOUTRVOL_ENA | WM8994_MIXOUTLVOL_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, val); + + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1); + val &= ~(WM8994_BIAS_ENA_MASK | WM8994_VMID_SEL_MASK | + WM8994_HPOUT2_ENA_MASK | WM8994_HPOUT1L_ENA_MASK | + WM8994_HPOUT1R_ENA_MASK | WM8994_SPKOUTL_ENA_MASK); + val |= (WM8994_BIAS_ENA | WM8994_VMID_SEL_NORMAL | WM8994_HPOUT2_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val); + + val = wm8994_read(codec, WM8994_AIF1_DAC1_FILTERS_1); + val &= ~(WM8994_AIF1DAC1_MUTE_MASK | WM8994_AIF1DAC1_MONO_MASK); + val |= (WM8994_AIF1DAC1_UNMUTE | WM8994_AIF1DAC1_MONO); + wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, val); + +} + +void wm8994_set_playback_headset(struct snd_soc_codec *codec) +{ + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + + u16 val; + + u16 testreturn1 = 0; + u16 testreturn2 = 0; + u16 testlow1 = 0; + u16 testhigh1 = 0; + u8 testlow = 0; + u8 testhigh = 0; + + DEBUG_LOG(""); + + wm8994_earsel_control(wm8994->pdata, 0); + + /* Enable the Timeslot0 to DAC1L */ + val = wm8994_read(codec, WM8994_DAC1_LEFT_MIXER_ROUTING); + val &= ~(WM8994_AIF1DAC1L_TO_DAC1L_MASK); + val |= WM8994_AIF1DAC1L_TO_DAC1L; + wm8994_write(codec, WM8994_DAC1_LEFT_MIXER_ROUTING, val); + + /* Enable the Timeslot0 to DAC1R */ + val = wm8994_read(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING); + val &= ~(WM8994_AIF1DAC1R_TO_DAC1R_MASK); + val |= WM8994_AIF1DAC1R_TO_DAC1R; + wm8994_write(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING, val); + + val = wm8994_read(codec, 0x102); + val &= ~(0x0003); + val = 0x0003; + wm8994_write(codec, 0x102, val); + + val = wm8994_read(codec, 0x56); + val &= ~(0x0003); + val = 0x0003; + wm8994_write(codec, 0x56, val); + + val = wm8994_read(codec, 0x102); + val &= ~(0x0000); + val = 0x0000; + wm8994_write(codec, 0x102, val); + + val = wm8994_read(codec, WM8994_CLASS_W_1); + val &= ~(0x0005); + val |= 0x0005; + wm8994_write(codec, WM8994_CLASS_W_1, val); + + val = wm8994_read(codec, WM8994_LEFT_OUTPUT_VOLUME); + val &= ~(WM8994_HPOUT1L_MUTE_N_MASK); + val |= (WM8994_HPOUT1L_MUTE_N); + wm8994_write(codec, WM8994_LEFT_OUTPUT_VOLUME, val); + + val = wm8994_read(codec, WM8994_RIGHT_OUTPUT_VOLUME); + val &= ~(WM8994_HPOUT1R_MUTE_N_MASK); + val |= (WM8994_HPOUT1R_MUTE_N); + wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, val); + + val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME); + val &= ~(WM8994_MIXOUTL_MUTE_N_MASK); + val |= (WM8994_MIXOUTL_MUTE_N); + wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, val); + + val = wm8994_read(codec, WM8994_RIGHT_OPGA_VOLUME); + val &= ~(WM8994_MIXOUTR_MUTE_N_MASK); + val |= (WM8994_MIXOUTR_MUTE_N); + wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val); + + if (wm8994->ringtone_active) + wm8994_set_codec_gain(codec, PLAYBACK_MODE, PLAYBACK_RING_HP); + else if (wm8994->cur_path == HP_NO_MIC) + wm8994_set_codec_gain(codec, PLAYBACK_MODE, PLAYBACK_HP_NO_MIC); + else + wm8994_set_codec_gain(codec, PLAYBACK_MODE, PLAYBACK_HP); + + val = wm8994_read(codec, WM8994_DC_SERVO_2); + val &= ~(0x03E0); + val = 0x03E0; + wm8994_write(codec, WM8994_DC_SERVO_2, val); + + /* Enable vmid,bias, hp left and right */ + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1); + val &= ~(WM8994_BIAS_ENA_MASK | WM8994_VMID_SEL_MASK | + WM8994_HPOUT1L_ENA_MASK | WM8994_HPOUT1R_ENA_MASK | + WM8994_SPKOUTR_ENA_MASK | WM8994_SPKOUTL_ENA_MASK); + val |= (WM8994_BIAS_ENA | WM8994_VMID_SEL_NORMAL | + WM8994_HPOUT1R_ENA | WM8994_HPOUT1L_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val); + + val = wm8994_read(codec, WM8994_ANALOGUE_HP_1); + val &= ~(0x0022); + val = 0x0022; + wm8994_write(codec, WM8994_ANALOGUE_HP_1, val); + + /* Enable Charge Pump */ + /* this is from wolfson */ + val = wm8994_read(codec, WM8994_CHARGE_PUMP_1); + val &= ~WM8994_CP_ENA_MASK ; + val |= WM8994_CP_ENA | WM8994_CP_ENA_DEFAULT; + wm8994_write(codec, WM8994_CHARGE_PUMP_1, val); + + msleep(5); + + /* Enable Dac1 and DAC2 and the Timeslot0 for AIF1 */ + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_5); + val &= ~(WM8994_DAC1R_ENA_MASK | WM8994_DAC1L_ENA_MASK | + WM8994_AIF1DAC1R_ENA_MASK | WM8994_AIF1DAC1L_ENA_MASK); + val |= (WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA | + WM8994_DAC1L_ENA | WM8994_DAC1R_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_5, val); + + /* Enable DAC1L to HPOUT1L path */ + val = wm8994_read(codec, WM8994_OUTPUT_MIXER_1); + val &= ~(WM8994_DAC1L_TO_HPOUT1L_MASK | WM8994_DAC1L_TO_MIXOUTL_MASK); + val |= WM8994_DAC1L_TO_MIXOUTL; + wm8994_write(codec, WM8994_OUTPUT_MIXER_1, val); + + /* Enable DAC1R to HPOUT1R path */ + val = wm8994_read(codec, WM8994_OUTPUT_MIXER_2); + val &= ~(WM8994_DAC1R_TO_HPOUT1R_MASK | WM8994_DAC1R_TO_MIXOUTR_MASK); + val |= WM8994_DAC1R_TO_MIXOUTR; + wm8994_write(codec, WM8994_OUTPUT_MIXER_2, val); + + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_3); + val &= ~(WM8994_MIXOUTLVOL_ENA_MASK | WM8994_MIXOUTRVOL_ENA_MASK | + WM8994_MIXOUTL_ENA_MASK | WM8994_MIXOUTR_ENA_MASK | + WM8994_SPKRVOL_ENA_MASK | WM8994_SPKLVOL_ENA_MASK); + val |= (WM8994_MIXOUTLVOL_ENA | WM8994_MIXOUTRVOL_ENA | + WM8994_MIXOUTL_ENA | WM8994_MIXOUTR_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, 0x0030); + + if (!wm8994->dc_servo[DCS_MEDIA]) { + wait_for_dc_servo(codec, + WM8994_DCS_TRIG_SERIES_0 | + WM8994_DCS_TRIG_SERIES_1); + + testreturn1 = wm8994_read(codec, WM8994_DC_SERVO_4); + + testlow = (signed char)(testreturn1 & 0xff); + testhigh = (signed char)((testreturn1>>8) & 0xff); + + testlow1 = ((signed short)(testlow-5)) & 0x00ff; + testhigh1 = (((signed short)(testhigh-5)<<8) & 0xff00); + testreturn2 = testlow1|testhigh1; + } else { + testreturn2 = wm8994->dc_servo[DCS_MEDIA]; + } + + wm8994_write(codec, WM8994_DC_SERVO_4, testreturn2); + wm8994->dc_servo[DCS_MEDIA] = testreturn2; + + wait_for_dc_servo(codec, + WM8994_DCS_TRIG_DAC_WR_0 | WM8994_DCS_TRIG_DAC_WR_1); + + /* Intermediate HP settings */ + val = wm8994_read(codec, WM8994_ANALOGUE_HP_1); + val &= ~(WM8994_HPOUT1R_DLY_MASK | WM8994_HPOUT1R_OUTP_MASK | + WM8994_HPOUT1R_RMV_SHORT_MASK | WM8994_HPOUT1L_DLY_MASK | + WM8994_HPOUT1L_OUTP_MASK | WM8994_HPOUT1L_RMV_SHORT_MASK); + val = (WM8994_HPOUT1L_RMV_SHORT | WM8994_HPOUT1L_OUTP| + WM8994_HPOUT1L_DLY | WM8994_HPOUT1R_RMV_SHORT | + WM8994_HPOUT1R_OUTP | WM8994_HPOUT1R_DLY); + wm8994_write(codec, WM8994_ANALOGUE_HP_1, val); + + /* Unmute DAC1 left */ + val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME); + val &= ~(WM8994_DAC1L_MUTE_MASK); + wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val); + + /* Unmute and volume ctrl RightDAC */ + val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME); + val &= ~(WM8994_DAC1R_MUTE_MASK); + wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val); + + /* Unmute the AF1DAC1 */ + val = wm8994_read(codec, WM8994_AIF1_DAC1_FILTERS_1); + val &= ~(WM8994_AIF1DAC1_MUTE_MASK | WM8994_AIF1DAC1_MONO_MASK); + val |= WM8994_AIF1DAC1_UNMUTE; + wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, val); + +} + +void wm8994_set_playback_speaker(struct snd_soc_codec *codec) +{ + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + + u16 val; + + DEBUG_LOG(""); + + /* Disable end point for preventing pop up noise.*/ + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1); + val &= ~(WM8994_SPKOUTL_ENA_MASK); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val); + + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_3); + val &= ~(WM8994_MIXOUTLVOL_ENA_MASK | WM8994_MIXOUTRVOL_ENA_MASK | + WM8994_MIXOUTL_ENA_MASK | WM8994_MIXOUTR_ENA_MASK | + WM8994_SPKRVOL_ENA_MASK | WM8994_SPKLVOL_ENA_MASK); + val |= WM8994_SPKLVOL_ENA; + wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, val); + + /* Speaker Volume Control */ + /* Unmute the SPKMIXVOLUME */ + val = wm8994_read(codec, WM8994_SPEAKER_VOLUME_LEFT); + val &= ~(WM8994_SPKOUTL_MUTE_N_MASK); + val |= (WM8994_SPKOUTL_MUTE_N); + wm8994_write(codec, WM8994_SPEAKER_VOLUME_LEFT, val); + + val = wm8994_read(codec, WM8994_SPEAKER_VOLUME_RIGHT); + val &= ~(WM8994_SPKOUTR_MUTE_N_MASK); + wm8994_write(codec, WM8994_SPEAKER_VOLUME_RIGHT, val); + + /* Unmute DAC1 left */ + val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME); + val &= ~(WM8994_DAC1L_MUTE_MASK); + wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val); + + /* Unmute and volume ctrl RightDAC */ + val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME); + val &= ~(WM8994_DAC1R_MUTE_MASK); + wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val); + + val = wm8994_read(codec, WM8994_SPKOUT_MIXERS); + val &= ~(WM8994_SPKMIXL_TO_SPKOUTL_MASK | + WM8994_SPKMIXR_TO_SPKOUTL_MASK | + WM8994_SPKMIXR_TO_SPKOUTR_MASK); + val |= WM8994_SPKMIXL_TO_SPKOUTL; + wm8994_write(codec, WM8994_SPKOUT_MIXERS, val); + + /* Unmute the DAC path */ + val = wm8994_read(codec, WM8994_SPEAKER_MIXER); + val &= ~(WM8994_DAC1L_TO_SPKMIXL_MASK); + val |= WM8994_DAC1L_TO_SPKMIXL; + wm8994_write(codec, WM8994_SPEAKER_MIXER, val); + + /* Eable DAC1 Left and timeslot left */ + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_5); + val &= ~(WM8994_DAC1L_ENA_MASK | WM8994_AIF1DAC1R_ENA_MASK | + WM8994_AIF1DAC1L_ENA_MASK); + val |= (WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA | WM8994_DAC1L_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_5, val); + + /* DRC setting */ + wm8994_write(codec, WM8994_AIF1_DRC1_1, 0x00BC); + wm8994_write(codec, WM8994_AIF1_DRC1_3, 0x0028); + wm8994_write(codec, WM8994_AIF1_DRC1_4, 0x0186); + + /* EQ AIF1 setting */ + wm8994_write(codec, WM8994_AIF1_DAC1_EQ_GAINS_1, 0x0019); + wm8994_write(codec, WM8994_AIF1_DAC1_EQ_GAINS_2, 0x6280); + wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_1_A, 0x0FC3); + wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_1_B, 0x03FD); + wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_1_PG, 0x00F4); + wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_2_A, 0x1F30); + wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_2_B, 0xF0CD); + wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_2_C, 0x040A); + wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_2_PG, 0x032C); + wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_3_A, 0x1C52); + wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_3_B, 0xF379); + wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_3_C, 0x040A); + wm8994_write(codec, WM8994_AIF1_DAC1_EQ_BAND_3_PG, 0x0DC1); + + if (wm8994->ringtone_active) + wm8994_set_codec_gain(codec, PLAYBACK_MODE, PLAYBACK_RING_SPK); + else + wm8994_set_codec_gain(codec, PLAYBACK_MODE, PLAYBACK_SPK); + + /* enable timeslot0 to left dac */ + val = wm8994_read(codec, WM8994_DAC1_LEFT_MIXER_ROUTING); + val &= ~(WM8994_AIF1DAC1L_TO_DAC1L_MASK); + val |= WM8994_AIF1DAC1L_TO_DAC1L; + wm8994_write(codec, WM8994_DAC1_LEFT_MIXER_ROUTING, val); + +#ifdef CONFIG_SND_VOODOO + voodoo_hook_playback_speaker(); +#endif + + /* Enbale bias,vmid and Left speaker */ + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1); + val &= ~(WM8994_BIAS_ENA_MASK | WM8994_VMID_SEL_MASK | + WM8994_HPOUT1L_ENA_MASK | WM8994_HPOUT1R_ENA_MASK | + WM8994_SPKOUTR_ENA_MASK | WM8994_SPKOUTL_ENA_MASK); + val |= (WM8994_BIAS_ENA | WM8994_VMID_SEL_NORMAL | WM8994_SPKOUTL_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val); + + /* Unmute */ + val = wm8994_read(codec, WM8994_AIF1_DAC1_FILTERS_1); + val &= ~(WM8994_AIF1DAC1_MUTE_MASK | WM8994_AIF1DAC1_MONO_MASK); + val |= (WM8994_AIF1DAC1_UNMUTE | WM8994_AIF1DAC1_MONO); + wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, val); + +} + +void wm8994_set_playback_speaker_headset(struct snd_soc_codec *codec) +{ + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + + u16 val; + + u16 nreadservo4val = 0; + u16 ncompensationresult = 0; + u16 ncompensationresultlow = 0; + u16 ncompensationresulthigh = 0; + u8 nservo4low = 0; + u8 nservo4high = 0; + + wm8994_earsel_control(wm8994->pdata, 0); + + /* Enable the Timeslot0 to DAC1L */ + val = wm8994_read(codec, WM8994_DAC1_LEFT_MIXER_ROUTING); + val &= ~(WM8994_AIF1DAC1L_TO_DAC1L_MASK); + val |= WM8994_AIF1DAC1L_TO_DAC1L; + wm8994_write(codec, WM8994_DAC1_LEFT_MIXER_ROUTING, val); + + /* Enable the Timeslot0 to DAC1R */ + val = wm8994_read(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING); + val &= ~(WM8994_AIF1DAC1R_TO_DAC1R_MASK); + val |= WM8994_AIF1DAC1R_TO_DAC1R; + wm8994_write(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING, val); + + /* Speaker Volume Control */ + val = wm8994_read(codec, WM8994_SPEAKER_VOLUME_LEFT); + val &= ~(WM8994_SPKOUTL_MUTE_N_MASK); + val |= (WM8994_SPKOUTL_MUTE_N); + wm8994_write(codec, WM8994_SPEAKER_VOLUME_LEFT, val); + + val = wm8994_read(codec, WM8994_SPEAKER_VOLUME_RIGHT); + val &= ~(WM8994_SPKOUTR_MUTE_N_MASK); + wm8994_write(codec, WM8994_SPEAKER_VOLUME_RIGHT, val); + + val = wm8994_read(codec, WM8994_SPKOUT_MIXERS); + val &= ~(WM8994_SPKMIXL_TO_SPKOUTL_MASK | + WM8994_SPKMIXR_TO_SPKOUTL_MASK | + WM8994_SPKMIXR_TO_SPKOUTR_MASK); + val |= WM8994_SPKMIXL_TO_SPKOUTL; + wm8994_write(codec, WM8994_SPKOUT_MIXERS, val); + + /* Unmute the DAC path */ + val = wm8994_read(codec, WM8994_SPEAKER_MIXER); + val &= ~(WM8994_DAC1L_TO_SPKMIXL_MASK); + val |= WM8994_DAC1L_TO_SPKMIXL; + wm8994_write(codec, WM8994_SPEAKER_MIXER, val); + + /* Configuring the Digital Paths */ + val = wm8994_read(codec, 0x102); + val &= ~(0x0003); + val = 0x0003; + wm8994_write(codec, 0x102, val); + + val = wm8994_read(codec, 0x56); + val &= ~(0x0003); + val = 0x0003; + wm8994_write(codec, 0x56, val); + + val = wm8994_read(codec, 0x102); + val &= ~(0x0000); + val = 0x0000; + wm8994_write(codec, 0x102, val); + + val = wm8994_read(codec, WM8994_CLASS_W_1); + val &= ~(0x0005); + val = 0x0005; + wm8994_write(codec, WM8994_CLASS_W_1, val); + + val = wm8994_read(codec, WM8994_LEFT_OUTPUT_VOLUME); + val &= ~(WM8994_HPOUT1L_MUTE_N_MASK); + val |= (WM8994_HPOUT1L_MUTE_N); + wm8994_write(codec, WM8994_LEFT_OUTPUT_VOLUME, val); + + val = wm8994_read(codec, WM8994_RIGHT_OUTPUT_VOLUME); + val &= ~(WM8994_HPOUT1R_MUTE_N_MASK); + val |= (WM8994_HPOUT1R_MUTE_N); + wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, val); + + /* DC Servo Series Count */ + val = 0x03E0; + wm8994_write(codec, WM8994_DC_SERVO_2, val); + + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1); + val &= ~(WM8994_BIAS_ENA_MASK | WM8994_VMID_SEL_MASK | + WM8994_HPOUT1L_ENA_MASK | WM8994_HPOUT1R_ENA_MASK | + WM8994_SPKOUTL_ENA_MASK); + val |= (WM8994_BIAS_ENA | WM8994_VMID_SEL_NORMAL | + WM8994_HPOUT1R_ENA | WM8994_HPOUT1L_ENA | + WM8994_SPKOUTL_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val); + + val = (WM8994_HPOUT1L_DLY | WM8994_HPOUT1R_DLY); + wm8994_write(codec, WM8994_ANALOGUE_HP_1, val); + + /* Enable Charge Pump */ + /* this is from wolfson */ + val = wm8994_read(codec, WM8994_CHARGE_PUMP_1); + val &= ~WM8994_CP_ENA_MASK ; + val |= WM8994_CP_ENA | WM8994_CP_ENA_DEFAULT; + wm8994_write(codec, WM8994_CHARGE_PUMP_1, val); + + msleep(5); + + /* Enable DAC1 and DAC2 and the Timeslot0 for AIF1 */ + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_5); + val &= ~(WM8994_DAC1R_ENA_MASK | WM8994_DAC1L_ENA_MASK | + WM8994_AIF1DAC1R_ENA_MASK | WM8994_AIF1DAC1L_ENA_MASK); + val |= (WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA | + WM8994_DAC1L_ENA | WM8994_DAC1R_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_5, val); + + /* Enbale DAC1L to HPOUT1L path */ + val = wm8994_read(codec, WM8994_OUTPUT_MIXER_1); + val &= ~(WM8994_DAC1L_TO_HPOUT1L_MASK | WM8994_DAC1L_TO_MIXOUTL_MASK); + val |= WM8994_DAC1L_TO_MIXOUTL; + wm8994_write(codec, WM8994_OUTPUT_MIXER_1, val); + + /* Enbale DAC1R to HPOUT1R path */ + val = wm8994_read(codec, WM8994_OUTPUT_MIXER_2); + val &= ~(WM8994_DAC1R_TO_HPOUT1R_MASK | WM8994_DAC1R_TO_MIXOUTR_MASK); + val |= WM8994_DAC1R_TO_MIXOUTR; + wm8994_write(codec, WM8994_OUTPUT_MIXER_2, val); + + /* Enbale bias,vmid, hp left and right and Left speaker */ + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_3); + val &= ~(WM8994_MIXOUTLVOL_ENA_MASK | WM8994_MIXOUTRVOL_ENA_MASK | + WM8994_MIXOUTL_ENA_MASK | WM8994_MIXOUTR_ENA_MASK | + WM8994_SPKLVOL_ENA_MASK); + val |= (WM8994_MIXOUTL_ENA | WM8994_MIXOUTR_ENA | WM8994_SPKLVOL_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, val); + + /* DC Servo */ + if (!wm8994->dc_servo[DCS_SPK_HP]) { + wait_for_dc_servo(codec, + WM8994_DCS_TRIG_SERIES_0 | + WM8994_DCS_TRIG_SERIES_1); + + nreadservo4val = wm8994_read(codec, WM8994_DC_SERVO_4); + nservo4low = (signed char)(nreadservo4val & 0xff); + nservo4high = (signed char)((nreadservo4val>>8) & 0xff); + + ncompensationresultlow = ((signed short)nservo4low - 5) + & 0x00ff; + ncompensationresulthigh = ((signed short)(nservo4high - 5)<<8) + & 0xff00; + ncompensationresult = ncompensationresultlow | + ncompensationresulthigh; + } else { + ncompensationresult = wm8994->dc_servo[DCS_SPK_HP]; + } + + wm8994_write(codec, WM8994_DC_SERVO_4, ncompensationresult); + wm8994->dc_servo[DCS_SPK_HP] = ncompensationresult; + + wait_for_dc_servo(codec, + WM8994_DCS_TRIG_DAC_WR_1 | WM8994_DCS_TRIG_DAC_WR_0); + + val = wm8994_read(codec, WM8994_ANALOGUE_HP_1); + val &= ~(WM8994_HPOUT1R_DLY_MASK | WM8994_HPOUT1R_OUTP_MASK | + WM8994_HPOUT1R_RMV_SHORT_MASK | WM8994_HPOUT1L_DLY_MASK | + WM8994_HPOUT1L_OUTP_MASK | WM8994_HPOUT1L_RMV_SHORT_MASK); + val |= (WM8994_HPOUT1L_RMV_SHORT | WM8994_HPOUT1L_OUTP | + WM8994_HPOUT1L_DLY | WM8994_HPOUT1R_RMV_SHORT | + WM8994_HPOUT1R_OUTP | WM8994_HPOUT1R_DLY); + wm8994_write(codec, WM8994_ANALOGUE_HP_1, val); + + if (wm8994->ringtone_active) + wm8994_set_codec_gain(codec, PLAYBACK_MODE, + PLAYBACK_RING_SPK_HP); + else + wm8994_set_codec_gain(codec, PLAYBACK_MODE, PLAYBACK_SPK_HP); + + val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME); + val &= ~(WM8994_DAC1L_MUTE_MASK); + wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val); + + val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME); + val &= ~(WM8994_DAC1R_MUTE_MASK); + wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val); + + val = wm8994_read(codec, WM8994_AIF1_DAC1_FILTERS_1); + val &= ~(WM8994_AIF1DAC1_MUTE_MASK | WM8994_AIF1DAC1_MONO_MASK); + val |= (WM8994_AIF1DAC1_UNMUTE | WM8994_AIF1DAC1_MONO); + wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, val); + +} + +void wm8994_set_playback_bluetooth(struct snd_soc_codec *codec) +{ + u16 val; + + DEBUG_LOG("BT Playback Path for SCO\n"); + + wm8994_set_bluetooth_common_setting(codec); + + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1); + val &= ~(WM8994_BIAS_ENA_MASK | WM8994_VMID_SEL_MASK); + val |= (WM8994_BIAS_ENA | WM8994_VMID_SEL_NORMAL); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val); + + wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, 0x0000); + + wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, 0x0000); + + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_4); + val &= ~(WM8994_AIF2ADCL_ENA_MASK | WM8994_AIF2ADCR_ENA_MASK); + val |= (WM8994_AIF2ADCL_ENA | WM8994_AIF2ADCR_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_4, val); + + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_5); + val &= ~(WM8994_AIF2DACL_ENA_MASK | WM8994_AIF2DACR_ENA_MASK | + WM8994_AIF1DAC1L_ENA_MASK | WM8994_AIF1DAC1R_ENA_MASK | + WM8994_DAC1L_ENA_MASK | WM8994_DAC1R_ENA_MASK); + val |= (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA | + WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA | + WM8994_DAC1L_ENA | WM8994_DAC1R_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_5, val); + + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_6); + val &= ~(WM8994_AIF3_ADCDAT_SRC_MASK); + val |= (0x0001 << WM8994_AIF3_ADCDAT_SRC_SHIFT); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_6, val); + + /* Mixer Routing*/ + val = wm8994_read(codec, WM8994_DAC2_LEFT_MIXER_ROUTING); + val &= ~(WM8994_AIF1DAC1L_TO_DAC2L_MASK); + val |= (WM8994_AIF1DAC1L_TO_DAC2L); + wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING, val); + + val = wm8994_read(codec, WM8994_DAC2_RIGHT_MIXER_ROUTING); + val &= ~(WM8994_AIF1DAC1R_TO_DAC2R_MASK); + val |= (WM8994_AIF1DAC1R_TO_DAC2R); + wm8994_write(codec, WM8994_DAC2_RIGHT_MIXER_ROUTING, val); + + /* Volume*/ + wm8994_write(codec, WM8994_DAC2_LEFT_VOLUME, 0x01C0); + wm8994_write(codec, WM8994_DAC2_RIGHT_VOLUME, 0x01C0); + + wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019); + + wm8994_write(codec, WM8994_OVERSAMPLING, 0X0000); + + /* GPIO Configuration*/ + wm8994_write(codec, WM8994_GPIO_8, WM8994_GP8_DIR | WM8994_GP8_DB); + wm8994_write(codec, WM8994_GPIO_9, WM8994_GP9_DB); + wm8994_write(codec, WM8994_GPIO_10, WM8994_GP10_DB); + wm8994_write(codec, WM8994_GPIO_11, WM8994_GP11_DB); + + /* Un-Mute*/ + val = wm8994_read(codec, WM8994_AIF1_DAC1_FILTERS_1); + val &= ~(WM8994_AIF1DAC1_MUTE_MASK | WM8994_AIF1DAC1_MONO_MASK); + val |= (WM8994_AIF1DAC1_UNMUTE); + wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, val); + +} + +static void wm8994_set_cdma_voicecall_common_setting(struct snd_soc_codec *codec) +{ + int val; + + wm8994_write(codec, WM8994_ANTIPOP_2, 0x0068); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, 0x0003); + msleep(50); + /* GPIO Configuration */ + wm8994_write(codec, WM8994_GPIO_1, 0xA101); + wm8994_write(codec, WM8994_GPIO_2, 0x8100); + wm8994_write(codec, WM8994_GPIO_3, 0x8100); + wm8994_write(codec, WM8994_GPIO_4, 0x8100); + wm8994_write(codec, WM8994_GPIO_5, 0x8100); + wm8994_write(codec, WM8994_GPIO_6, 0xA101); + wm8994_write(codec, WM8994_GPIO_7, 0x0100); + wm8994_write(codec, WM8994_GPIO_8, 0xA101); + wm8994_write(codec, WM8994_GPIO_9, 0xA101); + wm8994_write(codec, WM8994_GPIO_10, 0xA101); + wm8994_write(codec, WM8994_GPIO_11, 0xA101); + + wm8994_write(codec, WM8994_FLL2_CONTROL_2, 0x2F00); + wm8994_write(codec, WM8994_FLL2_CONTROL_3, 0x3126); + wm8994_write(codec, WM8994_FLL2_CONTROL_4, 0x0600); + wm8994_write(codec, WM8994_FLL2_CONTROL_5, 0x0C81); + wm8994_write(codec, WM8994_FLL2_CONTROL_1, 0x0001); + + val = wm8994_read(codec, WM8994_AIF2_CLOCKING_1); + if (!(val & WM8994_AIF2CLK_ENA)) + wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0009); + + wm8994_write(codec, WM8994_AIF2_RATE, 0x0003); + + /* AIF2 Interface - PCM Stereo mode */ + /* Left Justified, BCLK invert, LRCLK Invert */ + wm8994_write(codec, WM8994_AIF2_CONTROL_1, 0x4118); + + wm8994_write(codec, WM8994_AIF2_BCLK, 0x70); + wm8994_write(codec, WM8994_AIF2_CONTROL_2, 0x0000); + wm8994_write(codec, WM8994_AIF2_MASTER_SLAVE, 0); + + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_5); + val &= ~(WM8994_AIF2DACL_ENA_MASK | WM8994_AIF2DACR_ENA_MASK | + WM8994_AIF1DAC1L_ENA_MASK | WM8994_AIF1DAC1R_ENA_MASK | + WM8994_DAC1L_ENA_MASK | WM8994_DAC1R_ENA_MASK); + val |= (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA | + WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA | + WM8994_DAC1L_ENA | WM8994_DAC1R_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_5, val); + + /* Clocking */ + val = wm8994_read(codec, WM8994_CLOCKING_1); + val |= (WM8994_DSP_FS2CLK_ENA); + wm8994_write(codec, WM8994_CLOCKING_1, 0x000F); + + /* AIF1 & AIF2 Output is connected to DAC1 */ + val = wm8994_read(codec, WM8994_DAC1_LEFT_MIXER_ROUTING); + val &= ~(WM8994_AIF1DAC1L_TO_DAC1L_MASK | + WM8994_AIF2DACL_TO_DAC1L_MASK); + val |= (WM8994_AIF1DAC1L_TO_DAC1L | WM8994_AIF2DACL_TO_DAC1L); + wm8994_write(codec, WM8994_DAC1_LEFT_MIXER_ROUTING, val); + + val = wm8994_read(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING); + val &= ~(WM8994_AIF1DAC1R_TO_DAC1R_MASK | + WM8994_AIF2DACR_TO_DAC1R_MASK); + val |= (WM8994_AIF1DAC1R_TO_DAC1R | WM8994_AIF2DACR_TO_DAC1R); + wm8994_write(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING, val); + + wm8994_write(codec, 0x6, 0x0); +} + +static void wm8994_set_gsm_voicecall_common_setting(struct snd_soc_codec *codec) +{ + int val; + + /* GPIO Configuration */ + wm8994_write(codec, WM8994_GPIO_1, 0xA101); + wm8994_write(codec, WM8994_GPIO_2, 0x8100); + wm8994_write(codec, WM8994_GPIO_3, 0x0100); + wm8994_write(codec, WM8994_GPIO_4, 0x0100); + wm8994_write(codec, WM8994_GPIO_5, 0x8100); + wm8994_write(codec, WM8994_GPIO_6, 0xA101); + wm8994_write(codec, WM8994_GPIO_7, 0x0100); + wm8994_write(codec, WM8994_GPIO_8, 0xA101); + wm8994_write(codec, WM8994_GPIO_9, 0xA101); + wm8994_write(codec, WM8994_GPIO_10, 0xA101); + wm8994_write(codec, WM8994_GPIO_11, 0xA101); + + wm8994_write(codec, WM8994_FLL2_CONTROL_2, 0x2F00); + wm8994_write(codec, WM8994_FLL2_CONTROL_3, 0x3126); + wm8994_write(codec, WM8994_FLL2_CONTROL_4, 0x0100); + wm8994_write(codec, WM8994_FLL2_CONTROL_5, 0x0C88); + wm8994_write(codec, WM8994_FLL2_CONTROL_1, + WM8994_FLL2_FRACN_ENA | WM8994_FLL2_ENA); + + val = wm8994_read(codec, WM8994_AIF2_CLOCKING_1); + if (!(val & WM8994_AIF2CLK_ENA)) + wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0018); + + wm8994_write(codec, WM8994_AIF2_RATE, 0x3 << WM8994_AIF2CLK_RATE_SHIFT); + + /* AIF2 Interface - PCM Stereo mode */ + /* Left Justified, BCLK invert, LRCLK Invert */ + wm8994_write(codec, WM8994_AIF2_CONTROL_1, + WM8994_AIF2ADCR_SRC | WM8994_AIF2_BCLK_INV | 0x18); + + wm8994_write(codec, WM8994_AIF2_BCLK, 0x70); + wm8994_write(codec, WM8994_AIF2_CONTROL_2, 0x0000); + wm8994_write(codec, WM8994_AIF2_MASTER_SLAVE, WM8994_AIF2_MSTR | + WM8994_AIF2_CLK_FRC | WM8994_AIF2_LRCLK_FRC); + + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_5); + val &= ~(WM8994_AIF2DACL_ENA_MASK | WM8994_AIF2DACR_ENA_MASK | + WM8994_AIF1DAC1L_ENA_MASK | WM8994_AIF1DAC1R_ENA_MASK | + WM8994_DAC1L_ENA_MASK | WM8994_DAC1R_ENA_MASK); + val |= (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA | + WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA | + WM8994_DAC1L_ENA | WM8994_DAC1R_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_5, val); + + /* Clocking */ + val = wm8994_read(codec, WM8994_CLOCKING_1); + val |= (WM8994_DSP_FS2CLK_ENA); + wm8994_write(codec, WM8994_CLOCKING_1, val); + + wm8994_write(codec, WM8994_POWER_MANAGEMENT_6, 0x0); + + /* AIF1 & AIF2 Output is connected to DAC1 */ + val = wm8994_read(codec, WM8994_DAC1_LEFT_MIXER_ROUTING); + val &= ~(WM8994_AIF1DAC1L_TO_DAC1L_MASK | + WM8994_AIF2DACL_TO_DAC1L_MASK); + val |= (WM8994_AIF1DAC1L_TO_DAC1L | WM8994_AIF2DACL_TO_DAC1L); + wm8994_write(codec, WM8994_DAC1_LEFT_MIXER_ROUTING, val); + + val = wm8994_read(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING); + val &= ~(WM8994_AIF1DAC1R_TO_DAC1R_MASK | + WM8994_AIF2DACR_TO_DAC1R_MASK); + val |= (WM8994_AIF1DAC1R_TO_DAC1R | WM8994_AIF2DACR_TO_DAC1R); + wm8994_write(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING, val); + + wm8994_write(codec, 0x6, 0x0); +} + + +void wm8994_set_voicecall_common_setting(struct snd_soc_codec *codec) +{ + if (herring_is_cdma_wimax_dev()) + wm8994_set_cdma_voicecall_common_setting(codec); + else + wm8994_set_gsm_voicecall_common_setting(codec); + +#ifdef CONFIG_SND_VOODOO_RECORD_PRESETS + voodoo_hook_record_main_mic(); +#endif +} + +static void wm8994_set_cdma_voicecall_receiver(struct snd_soc_codec *codec) +{ + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + + int val; + + DEBUG_LOG(""); + + audio_ctrl_mic_bias_gpio(wm8994->pdata, 1); + + wm8994_write(codec, 0x0039, 0x0068); /* Anti Pop2 */ + wm8994_write(codec, 0x0001, 0x0003); /* Power Management 1 */ + msleep(50); + wm8994_write(codec, 0x0015, 0x0040); + wm8994_write(codec, 0x0702, 0x8100); /* GPIO 3. Speech PCM Clock */ + wm8994_write(codec, 0x0703, 0x8100); /* GPIO 4. Speech PCM Sync */ + /* GPIO 5. Speech PCM Data Out */ + wm8994_write(codec, 0x0704, 0x8100); + /* GPIO 7. Speech PCM Data Input */ + wm8994_write(codec, 0x0706, 0x0100); + wm8994_write(codec, 0x0244, 0x0C81); /* FLL2 Control 5 */ + wm8994_write(codec, 0x0241, 0x2F00); /* FLL2 Control 2 */ + wm8994_write(codec, 0x0243, 0x0600); /* FLL2 Control 4 */ + wm8994_write(codec, 0x0240, 0x0001); /* FLL2 Control 1 */ + msleep(3); + + /* AIF2 Clocking 1. Clock Source Select */ + wm8994_write(codec, 0x0204, 0x0008); + + /* Clocking 1. '0x000A' is added for a playback. (original = 0x0007) */ + wm8994_write(codec, 0x0208, 0x000F); + + wm8994_write(codec, 0x0620, 0x0000); /* Oversampling */ + wm8994_write(codec, 0x0211, 0x0003); /* AIF2 Rate */ + wm8994_write(codec, 0x0310, 0x4118); /* AIF2 Control 1 */ + /* AIF2 Control 2 pcm format is changed ulaw to linear */ + wm8994_write(codec, 0x0311, 0x0000); + wm8994_write(codec, 0x0520, 0x0000); /* AIF2 DAC Filter 1 */ + /* AIF2 Clocking 1. AIF2 Clock Enable */ + wm8994_write(codec, 0x0204, 0x0009); + + wm8994_write(codec, 0x0601, 0x0005); /* DAC1 Left Mixer Routing */ + /* DAC1 Right Mixer Routing(Playback) */ + wm8994_write(codec, 0x0602, 0x0001); + wm8994_write(codec, 0x0603, 0x018C); /* DAC2 Mixer Volumes */ + wm8994_write(codec, 0x0604, 0x0030); /* DAC2 Left Mixer Routing */ + wm8994_write(codec, 0x0605, 0x0010); /* DAC2 Right Mixer Routing */ + wm8994_write(codec, 0x0621, 0x01C0); /* Sidetone */ + wm8994_write(codec, 0x0002, 0x6240); /* Power Management 2 */ + wm8994_write(codec, 0x0028, 0x0030); /* Input Mixer 2 */ + wm8994_write(codec, 0x0018, 0x010A); + + /* Output Mixer 5 */ + val = wm8994_read(codec, 0x0031); + val &= ~(WM8994_DACL_MIXOUTL_VOL_MASK); + val |= 0x0000 << 0x0009; + wm8994_write(codec, 0x0031, val); + + /* Output Mixer 6 */ + val = wm8994_read(codec, 0x0032); + val &= ~(WM8994_DACR_MIXOUTR_VOL_MASK); + val |= 0x0000 << 0x0009; + wm8994_write(codec, 0x0032, val); + + /* Left OPGA Volume */ + val = wm8994_read(codec, 0x0020); + val &= ~(WM8994_MIXOUTL_MUTE_N_MASK | WM8994_MIXOUTL_VOL_MASK); + val |= (0x0100 | 0x0040 | 0x3D); + /* 05.24 Maximum ´ëºñ -6dB HAC ¿ë test -2 3B -> 39 */ + wm8994_write(codec, 0x0020, 0x01F9); + + /* Right OPGA Volume */ + val = wm8994_read(codec, 0x0021); + val &= ~(WM8994_MIXOUTR_MUTE_N_MASK | WM8994_MIXOUTR_VOL_MASK); + val |= (0x0100 | 0x0040 | 0x3D); + wm8994_write(codec, 0x0021, 0x01F9); + + wm8994_write(codec, 0x0312, 0x0000); /* Slave */ + /* sub mic */ + wm8994_write(codec, 0x0029, 0x0030); /* Input Mixer 3 */ + + wm8994_write(codec, 0x0015, 0x0000); + wm8994_write(codec, 0x0500, 0x0100); /* AIF2 ADC Left Volume */ + wm8994_write(codec, 0x0004, 0x2002); /* Power Management 4 */ + /* Power Management 5.'0x0303' added for a playback.(Original=0x2002) */ + wm8994_write(codec, 0x0005, 0x2303); + /* Power Management 3.'0x00F0' added for a playback.(Original=0x00A0) */ + wm8994_write(codec, 0x0003, 0x00F0); + wm8994_write(codec, 0x002D, 0x0001); /* Output Mixer 1 */ + wm8994_write(codec, 0x002E, 0x0001); /* Output Mixer 2(Playback) */ + /* HPOUT2 Mixer. '0x0008' added for a playback.(Original=0x0010) */ + wm8994_write(codec, 0x0033, 0x0018); + wm8994_write(codec, 0x0038, 0x0040); /* Anti Pop 1 */ + wm8994_write(codec, 0x0420, 0x0080); /* AIF1 DAC1 FIlter(Playback) */ + + /* HPOUT2 Volume */ + wm8994_write(codec, 0x001F, 0x0000); /* HPOUT2 Volume */ + + wm8994_write(codec, 0x0001, 0x0803); /* Power Management 1 */ + + /* DAC1 Left Volume */ + val = wm8994_read(codec, 0x0610); + val &= ~(WM8994_DAC1L_MUTE_MASK | WM8994_DAC1L_VOL_MASK); + val |= 0xC0; + wm8994_write(codec, 0x0610, 0x01C0); + + /* DAC1 Right Volume */ + val = wm8994_read(codec, 0x0611); + val &= ~(WM8994_DAC1R_MUTE_MASK | WM8994_DAC1R_VOL_MASK); + val |= 0xC0; + wm8994_write(codec, 0x0611, 0x01C0); + + /* Power Management 3(Playback) */ + wm8994_write(codec, 0x0003, 0x00F0); + + wm8994_write(codec, 0x06, 0x0000); + wm8994_write(codec, 0x0612, 0x01C0); /* DAC2 Left Volume */ + wm8994_write(codec, 0x0613, 0x01C0); /* DAC2 Right Volume */ + wm8994_write(codec, 0x0500, 0x01C0); /* AIF2 ADC Left Volume */ +} + +static void wm8994_set_gsm_voicecall_receiver(struct snd_soc_codec *codec) +{ + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + + int val; + + DEBUG_LOG(""); + + audio_ctrl_mic_bias_gpio(wm8994->pdata, 1); + + wm8994_set_voicecall_common_setting(codec); + + wm8994_write(codec, WM8994_CHARGE_PUMP_1, WM8994_CP_ENA_DEFAULT); + + wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, + WM8994_TSHUT_ENA | WM8994_TSHUT_OPDIS | WM8994_MIXINL_ENA | + WM8994_IN1L_ENA); + + wm8994_write(codec, WM8994_INPUT_MIXER_2, + WM8994_IN1LP_TO_IN1L | WM8994_IN1LN_TO_IN1L); + + /* Digital Path Enables and Unmutes */ + wm8994_write(codec, WM8994_POWER_MANAGEMENT_4, + WM8994_AIF2ADCL_ENA | WM8994_ADCL_ENA); + + wm8994_write(codec, WM8994_DAC2_MIXER_VOLUMES, 0x000C); + wm8994_write(codec, WM8994_DAC2_LEFT_VOLUME, 0x01C0); + wm8994_write(codec, WM8994_DAC2_RIGHT_VOLUME, 0x01C0); + + /* Tx -> AIF2 Path */ + wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING, + WM8994_ADC1_TO_DAC2L); + wm8994_write(codec, WM8994_DAC2_RIGHT_MIXER_ROUTING, + WM8994_ADC1_TO_DAC2R); + + wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019); + + /* Unmute IN1L PGA, update volume */ + val = wm8994_read(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME); + val &= ~(WM8994_IN1L_MUTE_MASK); + wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME, val); + + /* Unmute the PGA */ + val = wm8994_read(codec, WM8994_INPUT_MIXER_3); + val &= ~(WM8994_IN1L_TO_MIXINL_MASK); + val |= (WM8994_IN1L_TO_MIXINL); + wm8994_write(codec, WM8994_INPUT_MIXER_3, val); + + /* Volume Control - Output */ + val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME); + val &= ~(WM8994_MIXOUTL_MUTE_N_MASK); + val |= (WM8994_MIXOUTL_MUTE_N); + wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, val); + + val = wm8994_read(codec, WM8994_RIGHT_OPGA_VOLUME); + val &= ~(WM8994_MIXOUTR_MUTE_N_MASK); + val |= (WM8994_MIXOUTR_MUTE_N); + wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val); + + val = wm8994_read(codec, WM8994_HPOUT2_VOLUME); + val &= ~(WM8994_HPOUT2_MUTE_MASK); + wm8994_write(codec, WM8994_HPOUT2_VOLUME, val); + + wm8994_set_codec_gain(codec, VOICECALL_MODE, VOICECALL_RCV); + + /* Unmute DAC1 left */ + val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME); + val &= ~(WM8994_DAC1L_MUTE_MASK); + wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val); + + /* Unmute and volume ctrl RightDAC */ + val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME); + val &= ~(WM8994_DAC1R_MUTE_MASK); + wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val); + + /* Output Mixing */ + wm8994_write(codec, WM8994_OUTPUT_MIXER_1, WM8994_DAC1L_TO_MIXOUTL); + wm8994_write(codec, WM8994_OUTPUT_MIXER_2, WM8994_DAC1R_TO_MIXOUTR); + + /* Analogue Output Configuration */ + wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, + WM8994_MIXOUTLVOL_ENA | WM8994_MIXOUTRVOL_ENA | + WM8994_MIXOUTL_ENA | WM8994_MIXOUTR_ENA); + wm8994_write(codec, WM8994_HPOUT2_MIXER, WM8994_MIXOUTLVOL_TO_HPOUT2 | + WM8994_MIXOUTRVOL_TO_HPOUT2); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, + WM8994_HPOUT2_ENA | WM8994_VMID_SEL_NORMAL | WM8994_BIAS_ENA); + + wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, 0x0000); + wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, 0x0000); + +} + + +void wm8994_set_voicecall_receiver(struct snd_soc_codec *codec) +{ + if (herring_is_cdma_wimax_dev()) + wm8994_set_cdma_voicecall_receiver(codec); + else + wm8994_set_gsm_voicecall_receiver(codec); +} + +void wm8994_set_voicecall_headset(struct snd_soc_codec *codec) +{ + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + + int val; + + u16 testreturn1 = 0; + u16 testreturn2 = 0; + u16 testlow1 = 0; + u16 testhigh1 = 0; + u8 testlow = 0; + u8 testhigh = 0; + + DEBUG_LOG(""); + + wm8994_earsel_control(wm8994->pdata, 1); + + wm8994_set_voicecall_common_setting(codec); + + /* Digital Path Enables and Unmutes */ + if (wm8994->hw_version == 3) { /* H/W Rev D */ + wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING, + WM8994_ADC2_TO_DAC2L); + wm8994_write(codec, WM8994_DAC2_MIXER_VOLUMES, 0x0180); + wm8994_write(codec, WM8994_SIDETONE, 0x01C0); + } else { /* H/W Rev B */ + wm8994_write(codec, WM8994_DAC2_MIXER_VOLUMES, 0x000C); + wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING, + WM8994_ADC1_TO_DAC2L); + wm8994_write(codec, WM8994_SIDETONE, 0x01C1); + } + + /* Analogue Input Configuration */ + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_2); + val &= ~(WM8994_TSHUT_ENA_MASK | WM8994_TSHUT_OPDIS_MASK | + WM8994_MIXINR_ENA_MASK | WM8994_IN1R_ENA_MASK); + val |= (WM8994_TSHUT_ENA | WM8994_TSHUT_OPDIS | + WM8994_MIXINR_ENA | WM8994_IN1R_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, 0x6110); + + val = wm8994_read(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME); + val &= ~(WM8994_IN1R_MUTE_MASK); + wm8994_write(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, val); + + val = wm8994_read(codec, WM8994_INPUT_MIXER_4); + val &= ~(WM8994_IN1R_TO_MIXINR_MASK); + val |= (WM8994_IN1R_TO_MIXINR); + wm8994_write(codec, WM8994_INPUT_MIXER_4, val); + + val = wm8994_read(codec, WM8994_INPUT_MIXER_2); + val &= ~(WM8994_IN1RP_TO_IN1R_MASK | WM8994_IN1RN_TO_IN1R_MASK); + val |= (WM8994_IN1RP_TO_IN1R | WM8994_IN1RN_TO_IN1R); + wm8994_write(codec, WM8994_INPUT_MIXER_2, 0x0003); + + /* Unmute*/ + val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME); + val &= ~(WM8994_MIXOUTL_MUTE_N_MASK); + val |= (WM8994_MIXOUTL_MUTE_N); + wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, val); + + val = wm8994_read(codec, WM8994_RIGHT_OPGA_VOLUME); + val &= ~(WM8994_MIXOUTR_MUTE_N_MASK); + val |= (WM8994_MIXOUTR_MUTE_N); + wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val); + + wm8994_write(codec, WM8994_POWER_MANAGEMENT_4, 0x2001); + + val = wm8994_read(codec, 0x102); + val &= ~(0x0003); + val = 0x0003; + wm8994_write(codec, 0x102, val); + + val = wm8994_read(codec, 0x56); + val &= ~(0x0003); + val = 0x0003; + wm8994_write(codec, 0x56, val); + + val = wm8994_read(codec, 0x102); + val &= ~(0x0000); + val = 0x0000; + wm8994_write(codec, 0x102, val); + + val = wm8994_read(codec, WM8994_CLASS_W_1); + val &= ~(0x0005); + val |= 0x0005; + wm8994_write(codec, WM8994_CLASS_W_1, val); + + val = wm8994_read(codec, WM8994_LEFT_OUTPUT_VOLUME); + val &= ~(WM8994_HPOUT1L_MUTE_N_MASK); + val |= (WM8994_HPOUT1L_MUTE_N); + wm8994_write(codec, WM8994_LEFT_OUTPUT_VOLUME, val); + + val = wm8994_read(codec, WM8994_RIGHT_OUTPUT_VOLUME); + val &= ~(WM8994_HPOUT1R_MUTE_N_MASK); + val |= (WM8994_HPOUT1R_MUTE_N); + wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, val); + + val = wm8994_read(codec, WM8994_DC_SERVO_2); + val &= ~(0x03E0); + val = 0x03E0; + wm8994_write(codec, WM8994_DC_SERVO_2, val); + + wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, 0x0303); + + wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x0022); + wm8994_write(codec, WM8994_CHARGE_PUMP_1, 0x9F25); + + msleep(5); + + /* Analogue Output Configuration */ + wm8994_write(codec, WM8994_OUTPUT_MIXER_1, 0x0001); + wm8994_write(codec, WM8994_OUTPUT_MIXER_2, 0x0001); + + wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, 0x0030); + + if (herring_is_cdma_wimax_dev()) + wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0009); + else + wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019); + + if (!wm8994->dc_servo[DCS_VOICE]) { + wait_for_dc_servo(codec, + WM8994_DCS_TRIG_SERIES_0 | + WM8994_DCS_TRIG_SERIES_1); + + testreturn1 = wm8994_read(codec, WM8994_DC_SERVO_4); + + testlow = (signed char)(testreturn1 & 0xff); + testhigh = (signed char)((testreturn1>>8) & 0xff); + + testlow1 = ((signed short)testlow - 5) & 0x00ff; + testhigh1 = (((signed short)(testhigh - 5)<<8) & 0xff00); + testreturn2 = testlow1|testhigh1; + } else { + testreturn2 = wm8994->dc_servo[DCS_VOICE]; + } + + wm8994_write(codec, WM8994_DC_SERVO_4, testreturn2); + + wait_for_dc_servo(codec, + WM8994_DCS_TRIG_DAC_WR_0 | WM8994_DCS_TRIG_DAC_WR_1); + + wm8994->dc_servo[DCS_VOICE] = testreturn2; + + wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x00EE); + + wm8994_set_codec_gain(codec, VOICECALL_MODE, VOICECALL_HP); + + /* Unmute DAC1 left */ + val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME); + val &= ~(WM8994_DAC1L_MUTE_MASK); + wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val); + + /* Unmute and volume ctrl RightDAC */ + val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME); + val &= ~(WM8994_DAC1R_MUTE_MASK); + wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val); + + wm8994_write(codec, WM8994_DAC2_LEFT_VOLUME, 0x01C0); + + wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, 0x0000); + wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, 0x0000); + +} + +void wm8994_set_voicecall_headphone(struct snd_soc_codec *codec) +{ + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + + int val; + + u16 testreturn1 = 0; + u16 testreturn2 = 0; + u16 testlow1 = 0; + u16 testhigh1 = 0; + u8 testlow = 0; + u8 testhigh = 0; + + DEBUG_LOG(""); + audio_ctrl_mic_bias_gpio(wm8994->pdata, 1); + + wm8994_earsel_control(wm8994->pdata, 1); + + wm8994_set_voicecall_common_setting(codec); + + /* Digital Path Enables and Unmutes */ + wm8994_write(codec, WM8994_DAC2_MIXER_VOLUMES, 0x000C); + wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING, + WM8994_ADC1_TO_DAC2L); + + /* Analogue Input Configuration */ + wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, + WM8994_TSHUT_ENA | WM8994_TSHUT_OPDIS | WM8994_MIXINL_ENA | + WM8994_IN1L_ENA); + + /* Unmute IN1L PGA, update volume */ + val = wm8994_read(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME); + val &= ~(WM8994_IN1L_MUTE_MASK); + wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME, val); + + /* Unmute the PGA */ + val = wm8994_read(codec, WM8994_INPUT_MIXER_3); + val &= ~(WM8994_IN1L_TO_MIXINL_MASK); + val |= (WM8994_IN1L_TO_MIXINL); + wm8994_write(codec, WM8994_INPUT_MIXER_3, val); + + wm8994_write(codec, WM8994_INPUT_MIXER_2, + WM8994_IN1LP_TO_IN1L | WM8994_IN1LN_TO_IN1L); + + /* Unmute*/ + val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME); + val &= ~(WM8994_MIXOUTL_MUTE_N_MASK); + val |= (WM8994_MIXOUTL_MUTE_N); + wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, val); + + val = wm8994_read(codec, WM8994_RIGHT_OPGA_VOLUME); + val &= ~(WM8994_MIXOUTR_MUTE_N_MASK); + val |= (WM8994_MIXOUTR_MUTE_N); + wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val); + + /* Digital Path Enables and Unmutes */ + wm8994_write(codec, WM8994_POWER_MANAGEMENT_4, + WM8994_AIF2ADCL_ENA | WM8994_ADCL_ENA); + + val = wm8994_read(codec, 0x102); + val &= ~(0x0003); + val = 0x0003; + wm8994_write(codec, 0x102, val); + + val = wm8994_read(codec, 0x56); + val &= ~(0x0003); + val = 0x0003; + wm8994_write(codec, 0x56, val); + + val = wm8994_read(codec, 0x102); + val &= ~(0x0000); + val = 0x0000; + wm8994_write(codec, 0x102, val); + + val = wm8994_read(codec, WM8994_CLASS_W_1); + val &= ~(0x0005); + val |= 0x0005; + wm8994_write(codec, WM8994_CLASS_W_1, val); + + val = wm8994_read(codec, WM8994_LEFT_OUTPUT_VOLUME); + val &= ~(WM8994_HPOUT1L_MUTE_N_MASK); + val |= (WM8994_HPOUT1L_MUTE_N); + wm8994_write(codec, WM8994_LEFT_OUTPUT_VOLUME, val); + + val = wm8994_read(codec, WM8994_RIGHT_OUTPUT_VOLUME); + val &= ~(WM8994_HPOUT1R_MUTE_N_MASK); + val |= (WM8994_HPOUT1R_MUTE_N); + wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, val); + + val = wm8994_read(codec, WM8994_DC_SERVO_2); + val &= ~(0x03E0); + val = 0x03E0; + wm8994_write(codec, WM8994_DC_SERVO_2, val); + + wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, 0x0303); + + wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x0022); + wm8994_write(codec, WM8994_CHARGE_PUMP_1, 0x9F25); + + msleep(5); + + /* Analogue Output Configuration */ + wm8994_write(codec, WM8994_OUTPUT_MIXER_1, 0x0001); + wm8994_write(codec, WM8994_OUTPUT_MIXER_2, 0x0001); + + wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, 0x0030); + + if (herring_is_cdma_wimax_dev()) + wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0009); + else + wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019); + + if (!wm8994->dc_servo[DCS_VOICE]) { + wait_for_dc_servo(codec, + WM8994_DCS_TRIG_SERIES_0 | + WM8994_DCS_TRIG_SERIES_1); + + testreturn1 = wm8994_read(codec, WM8994_DC_SERVO_4); + + testlow = (signed char)(testreturn1 & 0xff); + testhigh = (signed char)((testreturn1>>8) & 0xff); + + testlow1 = ((signed short)testlow - 5) & 0x00ff; + testhigh1 = (((signed short)(testhigh - 5)<<8) & 0xff00); + testreturn2 = testlow1|testhigh1; + } else { + testreturn2 = wm8994->dc_servo[DCS_VOICE]; + } + + wm8994_write(codec, WM8994_DC_SERVO_4, testreturn2); + + wait_for_dc_servo(codec, + WM8994_DCS_TRIG_DAC_WR_0 | WM8994_DCS_TRIG_DAC_WR_1); + + wm8994->dc_servo[DCS_VOICE] = testreturn2; + + wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x00EE); + + wm8994_set_codec_gain(codec, VOICECALL_MODE, VOICECALL_HP_NO_MIC); + + /* Unmute DAC1 left */ + val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME); + val &= ~(WM8994_DAC1L_MUTE_MASK); + wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val); + + /* Unmute and volume ctrl RightDAC */ + val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME); + val &= ~(WM8994_DAC1R_MUTE_MASK); + wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val); + + wm8994_write(codec, WM8994_DAC2_LEFT_VOLUME, 0x01C0); + + wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, 0x0000); + wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, 0x0000); + +} + +void wm8994_set_voicecall_speaker(struct snd_soc_codec *codec) +{ + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + + int val; + + DEBUG_LOG(""); + + audio_ctrl_mic_bias_gpio(wm8994->pdata, 1); + + wm8994_set_voicecall_common_setting(codec); + + wm8994_write(codec, 0x601, 0x0005); + wm8994_write(codec, 0x602, 0x0005); + wm8994_write(codec, 0x603, 0x000C); + /* Tx -> AIF2 Path */ + wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING, + WM8994_ADC1_TO_DAC2L); + + /* Analogue Input Configuration*/ + wm8994_write(codec, 0x02, 0x6240); + wm8994_write(codec, WM8994_INPUT_MIXER_2, WM8994_IN1LP_TO_IN1L | + WM8994_IN1LN_TO_IN1L); + + val = wm8994_read(codec, WM8994_INPUT_MIXER_3); + val &= ~(WM8994_IN1L_TO_MIXINL_MASK); + val |= (WM8994_IN1L_TO_MIXINL); + wm8994_write(codec, WM8994_INPUT_MIXER_3, val); + + val = wm8994_read(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME); + val &= ~(WM8994_IN1L_MUTE_MASK); + wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME, val); + + /* Analogue Output Configuration*/ + wm8994_write(codec, 0x03, 0x0300); + + wm8994_write(codec, WM8994_POWER_MANAGEMENT_4, + WM8994_AIF2ADCL_ENA | WM8994_ADCL_ENA); + + if (herring_is_cdma_wimax_dev()) + wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0009); + else + wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019); + + val = wm8994_read(codec, WM8994_SPEAKER_VOLUME_LEFT); + val &= ~(WM8994_SPKOUTL_MUTE_N_MASK); + val |= (WM8994_SPKOUTL_MUTE_N); + wm8994_write(codec, WM8994_SPEAKER_VOLUME_LEFT, val); + + val = wm8994_read(codec, WM8994_SPEAKER_VOLUME_RIGHT); + val &= ~(WM8994_SPKOUTR_MUTE_N_MASK | WM8994_SPKOUTR_VOL_MASK); + wm8994_write(codec, WM8994_SPEAKER_VOLUME_RIGHT, val); + + val = wm8994_read(codec, WM8994_SPKOUT_MIXERS); + val &= ~(WM8994_SPKMIXL_TO_SPKOUTL_MASK | + WM8994_SPKMIXR_TO_SPKOUTL_MASK | + WM8994_SPKMIXR_TO_SPKOUTR_MASK); + val |= WM8994_SPKMIXL_TO_SPKOUTL; + wm8994_write(codec, WM8994_SPKOUT_MIXERS, val); + + wm8994_write(codec, 0x36, 0x0003); + /* Digital Path Enables and Unmutes*/ + + wm8994_write(codec, WM8994_SIDETONE, 0x01C0); + + + wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x0000); + wm8994_write(codec, WM8994_DC_SERVO_1, 0x0000); + + wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, + WM8994_SPKOUTL_ENA | WM8994_VMID_SEL_NORMAL | WM8994_BIAS_ENA); + + wm8994_set_codec_gain(codec, VOICECALL_MODE, VOICECALL_SPK); + + /* Unmute DAC1 left */ + val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME); + val &= ~(WM8994_DAC1L_MUTE_MASK); + wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val); + + /* Unmute and volume ctrl RightDAC */ + val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME); + val &= ~(WM8994_DAC1R_MUTE_MASK); + wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val); + + wm8994_write(codec, WM8994_DAC2_LEFT_VOLUME, 0x01C0); + wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, WM8994_AIF1DAC1_UNMUTE); + wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, WM8994_AIF1DAC2_UNMUTE); +} + +void wm8994_set_voicecall_bluetooth(struct snd_soc_codec *codec) +{ + int val; + + DEBUG_LOG(""); + + wm8994_set_voicecall_common_setting(codec); + + /* GPIO Configuration */ + wm8994_write(codec, WM8994_GPIO_8, WM8994_GP8_DIR | WM8994_GP8_DB); + wm8994_write(codec, WM8994_GPIO_9, WM8994_GP9_DB); + wm8994_write(codec, WM8994_GPIO_10, WM8994_GP10_DB); + wm8994_write(codec, WM8994_GPIO_11, WM8994_GP11_DB); + + /* Digital Path Enables and Unmutes */ + val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1); + val &= ~(WM8994_SPKOUTL_ENA_MASK | WM8994_HPOUT2_ENA_MASK | + WM8994_HPOUT1L_ENA_MASK | WM8994_HPOUT1R_ENA_MASK); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val); + + wm8994_write(codec, WM8994_POWER_MANAGEMENT_4, + WM8994_AIF2ADCL_ENA | WM8994_ADCL_ENA); + + /* If Input MIC is enabled, bluetooth Rx is muted. */ + wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME, + WM8994_IN1L_MUTE); + wm8994_write(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, + WM8994_IN1R_MUTE); + wm8994_write(codec, WM8994_INPUT_MIXER_2, 0x00); + wm8994_write(codec, WM8994_INPUT_MIXER_3, 0x00); + wm8994_write(codec, WM8994_INPUT_MIXER_4, 0x00); + + /* + * for BT DTMF Play + * Rx Path: AIF2ADCDAT2 select + * CP(CALL) Path:GPIO5/DACDAT2 select + * AP(DTMF) Path: DACDAT1 select + * Tx Path: GPIO8/DACDAT3 select + */ + + wm8994_write(codec, WM8994_POWER_MANAGEMENT_6, 0x000C); + + /* AIF1 & AIF2 Output is connected to DAC1 */ + wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING, + WM8994_AIF2DACL_TO_DAC2L | WM8994_AIF1DAC1L_TO_DAC2L); + wm8994_write(codec, WM8994_DAC2_RIGHT_MIXER_ROUTING, + WM8994_AIF2DACR_TO_DAC2R | WM8994_AIF1DAC1R_TO_DAC2R); + + if (herring_is_cdma_wimax_dev()) + wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0009); + else + wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019); + + wm8994_write(codec, WM8994_DAC2_MIXER_VOLUMES, 0x000C); + + wm8994_write(codec, WM8994_DAC2_LEFT_VOLUME, 0x01C0); + wm8994_write(codec, WM8994_DAC2_RIGHT_VOLUME, 0x01C0); + + wm8994_write(codec, WM8994_OVERSAMPLING, 0X0000); + + wm8994_set_codec_gain(codec, VOICECALL_MODE, VOICECALL_BT); + + /* Unmute DAC1 left */ + val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME); + val &= ~(WM8994_DAC1L_MUTE_MASK); + wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val); + + /* Unmute and volume ctrl RightDAC */ + val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME); + val &= ~(WM8994_DAC1R_MUTE_MASK); + wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val); + + wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, 0x0000); + wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, 0x0000); +} + +void wm8994_set_voicecall_tty_vco(struct snd_soc_codec *codec) +{ + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + + int val; + + u16 testreturn1 = 0; + u16 testreturn2 = 0; + u16 testlow1 = 0; + u16 testhigh1 = 0; + u8 testlow = 0; + u8 testhigh = 0; + + DEBUG_LOG(""); + audio_ctrl_mic_bias_gpio(wm8994->pdata, 1); + + wm8994_earsel_control(wm8994->pdata, 1); + + wm8994_set_voicecall_common_setting(codec); + + /* Digital Path Enables and Unmutes */ + wm8994_write(codec, WM8994_DAC2_MIXER_VOLUMES, 0x000C); + wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING, + WM8994_ADC1_TO_DAC2L); + + /* Analogue Input Configuration */ + wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, + WM8994_TSHUT_ENA | WM8994_TSHUT_OPDIS | WM8994_MIXINL_ENA | + WM8994_IN1L_ENA); + + /* Unmute IN1L PGA, update volume */ + val = wm8994_read(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME); + val &= ~(WM8994_IN1L_MUTE_MASK); + wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME, val); + + /* Unmute the PGA */ + val = wm8994_read(codec, WM8994_INPUT_MIXER_3); + val &= ~(WM8994_IN1L_TO_MIXINL_MASK); + val |= (WM8994_IN1L_TO_MIXINL); + wm8994_write(codec, WM8994_INPUT_MIXER_3, val); + + wm8994_write(codec, WM8994_INPUT_MIXER_2, + WM8994_IN1LP_TO_IN1L | WM8994_IN1LN_TO_IN1L); + + /* Unmute*/ + val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME); + val &= ~(WM8994_MIXOUTL_MUTE_N_MASK); + val |= (WM8994_MIXOUTL_MUTE_N); + wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, val); + + val = wm8994_read(codec, WM8994_RIGHT_OPGA_VOLUME); + val &= ~(WM8994_MIXOUTR_MUTE_N_MASK); + val |= (WM8994_MIXOUTR_MUTE_N); + wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val); + + /* Digital Path Enables and Unmutes */ + wm8994_write(codec, WM8994_POWER_MANAGEMENT_4, + WM8994_AIF2ADCL_ENA | WM8994_ADCL_ENA); + + val = wm8994_read(codec, 0x102); + val &= ~(0x0003); + val = 0x0003; + wm8994_write(codec, 0x102, val); + + val = wm8994_read(codec, 0x56); + val &= ~(0x0003); + val = 0x0003; + wm8994_write(codec, 0x56, val); + + val = wm8994_read(codec, 0x102); + val &= ~(0x0000); + val = 0x0000; + wm8994_write(codec, 0x102, val); + + val = wm8994_read(codec, WM8994_CLASS_W_1); + val &= ~(0x0005); + val |= 0x0005; + wm8994_write(codec, WM8994_CLASS_W_1, val); + + val = wm8994_read(codec, WM8994_LEFT_OUTPUT_VOLUME); + val &= ~(WM8994_HPOUT1L_MUTE_N_MASK); + val |= (WM8994_HPOUT1L_MUTE_N); + wm8994_write(codec, WM8994_LEFT_OUTPUT_VOLUME, val); + + val = wm8994_read(codec, WM8994_RIGHT_OUTPUT_VOLUME); + val &= ~(WM8994_HPOUT1R_MUTE_N_MASK); + val |= (WM8994_HPOUT1R_MUTE_N); + wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, val); + + val = wm8994_read(codec, WM8994_DC_SERVO_2); + val &= ~(0x03E0); + val = 0x03E0; + wm8994_write(codec, WM8994_DC_SERVO_2, val); + + wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, 0x0303); + + wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x0022); + wm8994_write(codec, WM8994_CHARGE_PUMP_1, 0x9F25); + + msleep(5); + + /* Analogue Output Configuration */ + wm8994_write(codec, WM8994_OUTPUT_MIXER_1, 0x0001); + wm8994_write(codec, WM8994_OUTPUT_MIXER_2, 0x0001); + + wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, 0x0030); + + if (herring_is_cdma_wimax_dev()) + wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0009); + else + wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019); + + if (!wm8994->dc_servo[DCS_VOICE]) { + wait_for_dc_servo(codec, + WM8994_DCS_TRIG_SERIES_0 | + WM8994_DCS_TRIG_SERIES_1); + + testreturn1 = wm8994_read(codec, WM8994_DC_SERVO_4); + + testlow = (signed char)(testreturn1 & 0xff); + testhigh = (signed char)((testreturn1>>8) & 0xff); + + testlow1 = ((signed short)testlow - 5) & 0x00ff; + testhigh1 = (((signed short)(testhigh - 5)<<8) & 0xff00); + testreturn2 = testlow1|testhigh1; + } else { + testreturn2 = wm8994->dc_servo[DCS_VOICE]; + } + + wm8994_write(codec, WM8994_DC_SERVO_4, testreturn2); + + wait_for_dc_servo(codec, + WM8994_DCS_TRIG_DAC_WR_0 | WM8994_DCS_TRIG_DAC_WR_1); + + wm8994->dc_servo[DCS_VOICE] = testreturn2; + + wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x00EE); + + wm8994_set_codec_gain(codec, VOICECALL_MODE, VOICECALL_TTY_VCO); + + /* Unmute DAC1 left */ + val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME); + val &= ~(WM8994_DAC1L_MUTE_MASK); + wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val); + + /* Unmute and volume ctrl RightDAC */ + val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME); + val &= ~(WM8994_DAC1R_MUTE_MASK); + wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val); + + wm8994_write(codec, WM8994_DAC2_LEFT_VOLUME, 0x01C0); + + wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, 0x0000); + wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, 0x0000); + +} + +void wm8994_set_voicecall_tty_hco(struct snd_soc_codec *codec) +{ + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + + int val; + + u16 testreturn1 = 0; + u16 testreturn2 = 0; + u16 testlow1 = 0; + u16 testhigh1 = 0; + u8 testlow = 0; + u8 testhigh = 0; + + DEBUG_LOG(""); + + wm8994_earsel_control(wm8994->pdata, 1); + + wm8994_set_voicecall_common_setting(codec); + + /* Digital Path Enables and Unmutes */ + if (wm8994->hw_version == 3) { /* H/W Rev D */ + wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING, + WM8994_ADC2_TO_DAC2L); + wm8994_write(codec, WM8994_DAC2_MIXER_VOLUMES, 0x0180); + wm8994_write(codec, WM8994_SIDETONE, 0x01C0); + } else { /* H/W Rev B */ + wm8994_write(codec, WM8994_DAC2_MIXER_VOLUMES, 0x000C); + wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING, + WM8994_ADC1_TO_DAC2L); + wm8994_write(codec, WM8994_SIDETONE, 0x01C1); + } + + /* Analogue Input Configuration */ + val = (WM8994_TSHUT_ENA | WM8994_TSHUT_OPDIS | + WM8994_MIXINR_ENA | WM8994_IN1R_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, val); + + val = wm8994_read(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME); + val &= ~(WM8994_IN1R_MUTE_MASK); + wm8994_write(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, val); + + val = wm8994_read(codec, WM8994_INPUT_MIXER_4); + val &= ~(WM8994_IN1R_TO_MIXINR_MASK); + val |= (WM8994_IN1R_TO_MIXINR); + wm8994_write(codec, WM8994_INPUT_MIXER_4, val); + + val = (WM8994_IN1RP_TO_IN1R | WM8994_IN1RN_TO_IN1R); + wm8994_write(codec, WM8994_INPUT_MIXER_2, val); + + /* Unmute*/ + val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME); + val &= ~(WM8994_MIXOUTL_MUTE_N_MASK); + val |= (WM8994_MIXOUTL_MUTE_N); + wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, val); + + val = wm8994_read(codec, WM8994_RIGHT_OPGA_VOLUME); + val &= ~(WM8994_MIXOUTR_MUTE_N_MASK); + val |= (WM8994_MIXOUTR_MUTE_N); + wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val); + + wm8994_write(codec, WM8994_POWER_MANAGEMENT_4, + WM8994_AIF2ADCL_ENA | WM8994_ADCR_ENA); + + val = wm8994_read(codec, 0x102); + val &= ~(0x0003); + val = 0x0003; + wm8994_write(codec, 0x102, val); + + val = wm8994_read(codec, 0x56); + val &= ~(0x0003); + val = 0x0003; + wm8994_write(codec, 0x56, val); + + val = wm8994_read(codec, 0x102); + val &= ~(0x0000); + val = 0x0000; + wm8994_write(codec, 0x102, val); + + val = wm8994_read(codec, WM8994_CLASS_W_1); + val &= ~(0x0005); + val |= 0x0005; + wm8994_write(codec, WM8994_CLASS_W_1, val); + + val = wm8994_read(codec, WM8994_LEFT_OUTPUT_VOLUME); + val &= ~(WM8994_HPOUT1L_MUTE_N_MASK); + val |= (WM8994_HPOUT1L_MUTE_N); + wm8994_write(codec, WM8994_LEFT_OUTPUT_VOLUME, val); + + val = wm8994_read(codec, WM8994_RIGHT_OUTPUT_VOLUME); + val &= ~(WM8994_HPOUT1R_MUTE_N_MASK); + val |= (WM8994_HPOUT1R_MUTE_N); + wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, val); + + val = wm8994_read(codec, WM8994_DC_SERVO_2); + val &= ~(0x03E0); + val = 0x03E0; + wm8994_write(codec, WM8994_DC_SERVO_2, val); + + wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, + WM8994_HPOUT2_ENA | WM8994_VMID_SEL_NORMAL | WM8994_BIAS_ENA); + + wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x0022); + wm8994_write(codec, WM8994_CHARGE_PUMP_1, 0x9F25); + + msleep(5); + + /* Analogue Output Configuration */ + wm8994_write(codec, WM8994_OUTPUT_MIXER_1, 0x0001); + wm8994_write(codec, WM8994_OUTPUT_MIXER_2, 0x0001); + wm8994_write(codec, WM8994_HPOUT2_MIXER, WM8994_MIXOUTLVOL_TO_HPOUT2 | + WM8994_MIXOUTRVOL_TO_HPOUT2); + + wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, + WM8994_MIXOUTLVOL_ENA | WM8994_MIXOUTRVOL_ENA | + WM8994_MIXOUTL_ENA | WM8994_MIXOUTR_ENA); + + if (herring_is_cdma_wimax_dev()) + wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0009); + else + wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019); + + if (!wm8994->dc_servo[DCS_VOICE]) { + wait_for_dc_servo(codec, + WM8994_DCS_TRIG_SERIES_0 | + WM8994_DCS_TRIG_SERIES_1); + + testreturn1 = wm8994_read(codec, WM8994_DC_SERVO_4); + + testlow = (signed char)(testreturn1 & 0xff); + testhigh = (signed char)((testreturn1>>8) & 0xff); + + testlow1 = ((signed short)testlow - 5) & 0x00ff; + testhigh1 = (((signed short)(testhigh - 5)<<8) & 0xff00); + testreturn2 = testlow1|testhigh1; + } else { + testreturn2 = wm8994->dc_servo[DCS_VOICE]; + } + + wm8994_write(codec, WM8994_DC_SERVO_4, testreturn2); + + wait_for_dc_servo(codec, + WM8994_DCS_TRIG_DAC_WR_0 | WM8994_DCS_TRIG_DAC_WR_1); + + wm8994->dc_servo[DCS_VOICE] = testreturn2; + + wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x00EE); + + val = wm8994_read(codec, WM8994_HPOUT2_VOLUME); + val &= ~(WM8994_HPOUT2_MUTE_MASK); + wm8994_write(codec, WM8994_HPOUT2_VOLUME, val); + + wm8994_set_codec_gain(codec, VOICECALL_MODE, VOICECALL_TTY_HCO); + + /* Unmute DAC1 left */ + val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME); + val &= ~(WM8994_DAC1L_MUTE_MASK); + wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val); + + /* Unmute and volume ctrl RightDAC */ + val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME); + val &= ~(WM8994_DAC1R_MUTE_MASK); + wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val); + + wm8994_write(codec, WM8994_DAC2_LEFT_VOLUME, 0x01C0); + + wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, 0x0000); + wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, 0x0000); + +} + +void wm8994_set_voicecall_tty_full(struct snd_soc_codec *codec) +{ + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + + int val; + + u16 testreturn1 = 0; + u16 testreturn2 = 0; + u16 testlow1 = 0; + u16 testhigh1 = 0; + u8 testlow = 0; + u8 testhigh = 0; + + DEBUG_LOG(""); + + wm8994_earsel_control(wm8994->pdata, 1); + + wm8994_set_voicecall_common_setting(codec); + + /* Digital Path Enables and Unmutes */ + if (wm8994->hw_version == 3) { /* H/W Rev D */ + wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING, + WM8994_ADC2_TO_DAC2L); + wm8994_write(codec, WM8994_DAC2_MIXER_VOLUMES, 0x0180); + wm8994_write(codec, WM8994_SIDETONE, 0x01C0); + } else { /* H/W Rev B */ + wm8994_write(codec, WM8994_DAC2_MIXER_VOLUMES, 0x000C); + wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING, + WM8994_ADC1_TO_DAC2L); + wm8994_write(codec, WM8994_SIDETONE, 0x01C1); + } + + /* Analogue Input Configuration */ + val = (WM8994_TSHUT_ENA | WM8994_TSHUT_OPDIS | + WM8994_MIXINR_ENA | WM8994_IN1R_ENA); + wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, val); + + val = wm8994_read(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME); + val &= ~(WM8994_IN1R_MUTE_MASK); + wm8994_write(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, val); + + val = wm8994_read(codec, WM8994_INPUT_MIXER_4); + val &= ~(WM8994_IN1R_TO_MIXINR_MASK); + val |= (WM8994_IN1R_TO_MIXINR); + wm8994_write(codec, WM8994_INPUT_MIXER_4, val); + + val = (WM8994_IN1RP_TO_IN1R | WM8994_IN1RN_TO_IN1R); + wm8994_write(codec, WM8994_INPUT_MIXER_2, val); + + /* Unmute*/ + val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME); + val &= ~(WM8994_MIXOUTL_MUTE_N_MASK); + val |= (WM8994_MIXOUTL_MUTE_N); + wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, val); + + val = wm8994_read(codec, WM8994_RIGHT_OPGA_VOLUME); + val &= ~(WM8994_MIXOUTR_MUTE_N_MASK); + val |= (WM8994_MIXOUTR_MUTE_N); + wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val); + + wm8994_write(codec, WM8994_POWER_MANAGEMENT_4, 0x2001); + + val = wm8994_read(codec, 0x102); + val &= ~(0x0003); + val = 0x0003; + wm8994_write(codec, 0x102, val); + + val = wm8994_read(codec, 0x56); + val &= ~(0x0003); + val = 0x0003; + wm8994_write(codec, 0x56, val); + + val = wm8994_read(codec, 0x102); + val &= ~(0x0000); + val = 0x0000; + wm8994_write(codec, 0x102, val); + + val = wm8994_read(codec, WM8994_CLASS_W_1); + val &= ~(0x0005); + val |= 0x0005; + wm8994_write(codec, WM8994_CLASS_W_1, val); + + val = wm8994_read(codec, WM8994_LEFT_OUTPUT_VOLUME); + val &= ~(WM8994_HPOUT1L_MUTE_N_MASK); + val |= (WM8994_HPOUT1L_MUTE_N); + wm8994_write(codec, WM8994_LEFT_OUTPUT_VOLUME, val); + + val = wm8994_read(codec, WM8994_RIGHT_OUTPUT_VOLUME); + val &= ~(WM8994_HPOUT1R_MUTE_N_MASK); + val |= (WM8994_HPOUT1R_MUTE_N); + wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, val); + + val = wm8994_read(codec, WM8994_DC_SERVO_2); + val &= ~(0x03E0); + val = 0x03E0; + wm8994_write(codec, WM8994_DC_SERVO_2, val); + + wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, 0x0303); + + wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x0022); + wm8994_write(codec, WM8994_CHARGE_PUMP_1, 0x9F25); + + msleep(5); + + /* Analogue Output Configuration */ + wm8994_write(codec, WM8994_OUTPUT_MIXER_1, 0x0001); + wm8994_write(codec, WM8994_OUTPUT_MIXER_2, 0x0001); + + wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, 0x0030); + + if (herring_is_cdma_wimax_dev()) + wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0009); + else + wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019); + + if (!wm8994->dc_servo[DCS_VOICE]) { + wait_for_dc_servo(codec, + WM8994_DCS_TRIG_SERIES_0 | + WM8994_DCS_TRIG_SERIES_1); + + testreturn1 = wm8994_read(codec, WM8994_DC_SERVO_4); + + testlow = (signed char)(testreturn1 & 0xff); + testhigh = (signed char)((testreturn1>>8) & 0xff); + + testlow1 = ((signed short)testlow - 5) & 0x00ff; + testhigh1 = (((signed short)(testhigh - 5)<<8) & 0xff00); + testreturn2 = testlow1|testhigh1; + } else { + testreturn2 = wm8994->dc_servo[DCS_VOICE]; + } + + wm8994_write(codec, WM8994_DC_SERVO_4, testreturn2); + + wait_for_dc_servo(codec, + WM8994_DCS_TRIG_DAC_WR_0 | WM8994_DCS_TRIG_DAC_WR_1); + + wm8994->dc_servo[DCS_VOICE] = testreturn2; + + wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x00EE); + + wm8994_set_codec_gain(codec, VOICECALL_MODE, VOICECALL_TTY_FULL); + + /* Unmute DAC1 left */ + val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME); + val &= ~(WM8994_DAC1L_MUTE_MASK); + wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val); + + /* Unmute and volume ctrl RightDAC */ + val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME); + val &= ~(WM8994_DAC1R_MUTE_MASK); + wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val); + + wm8994_write(codec, WM8994_DAC2_LEFT_VOLUME, 0x01C0); + + wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, 0x0000); + wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, 0x0000); + +} + +int wm8994_set_codec_gain(struct snd_soc_codec *codec, u16 mode, u16 device) +{ + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); + int i; + u32 gain_set_bits = COMMON_SET_BIT; + u16 val; + struct gain_info_t *default_gain_table_p = NULL; + int table_num = 0; + + if (mode == PLAYBACK_MODE) { + + if (herring_is_cdma_wimax_dev()) + default_gain_table_p = cdma_playback_gain_table; + else + default_gain_table_p = playback_gain_table; + + table_num = PLAYBACK_GAIN_NUM; + + switch (device) { + case PLAYBACK_RCV: + gain_set_bits |= PLAYBACK_RCV; + break; + case PLAYBACK_SPK: + gain_set_bits |= PLAYBACK_SPK; + break; + case PLAYBACK_HP: + gain_set_bits |= PLAYBACK_HP; + break; + case PLAYBACK_BT: + gain_set_bits |= PLAYBACK_BT; + break; + case PLAYBACK_SPK_HP: + gain_set_bits |= PLAYBACK_SPK_HP; + break; + case PLAYBACK_RING_SPK: + gain_set_bits |= (PLAYBACK_SPK | PLAYBACK_RING_SPK); + break; + case PLAYBACK_RING_HP: + gain_set_bits |= (PLAYBACK_HP | PLAYBACK_RING_HP); + break; + case PLAYBACK_RING_SPK_HP: + gain_set_bits |= (PLAYBACK_SPK_HP | + PLAYBACK_RING_SPK_HP); + break; + case PLAYBACK_HP_NO_MIC: + gain_set_bits |= PLAYBACK_HP_NO_MIC; + break; + default: + pr_err("playback modo gain flag is wrong\n"); + break; + } + } else if (mode == VOICECALL_MODE) { + if (herring_is_cdma_wimax_dev()) + default_gain_table_p = cdma_voicecall_gain_table; + else + default_gain_table_p = voicecall_gain_table; + table_num = VOICECALL_GAIN_NUM; + + switch (device) { + case VOICECALL_RCV: + gain_set_bits |= VOICECALL_RCV; + break; + case VOICECALL_SPK: + gain_set_bits |= VOICECALL_SPK; + break; + case VOICECALL_HP: + gain_set_bits |= VOICECALL_HP; + break; + case VOICECALL_HP_NO_MIC: + gain_set_bits |= VOICECALL_HP_NO_MIC; + break; + case VOICECALL_BT: + gain_set_bits |= VOICECALL_BT; + break; + case VOICECALL_TTY_VCO: + gain_set_bits |= (VOICECALL_HP_NO_MIC | VOICECALL_TTY_VCO); + break; + case VOICECALL_TTY_HCO: + gain_set_bits |= (VOICECALL_RCV | VOICECALL_TTY_HCO); + break; + case VOICECALL_TTY_FULL: + gain_set_bits |= (VOICECALL_HP | VOICECALL_TTY_FULL); + break; + default: + pr_err("voicemode gain flag is wrong\n"); + } + } else if (mode == RECORDING_MODE) { + default_gain_table_p = recording_gain_table; + table_num = RECORDING_GAIN_NUM; + + switch (device) { + case RECORDING_MAIN: + gain_set_bits |= RECORDING_MAIN; + break; + case RECORDING_HP: + gain_set_bits |= RECORDING_HP; + break; + case RECORDING_BT: + gain_set_bits |= RECORDING_BT; + break; + case RECORDING_REC_MAIN: + gain_set_bits |= RECORDING_REC_MAIN; + break; + case RECORDING_REC_HP: + gain_set_bits |= RECORDING_REC_HP; + break; + case RECORDING_REC_BT: + gain_set_bits |= RECORDING_REC_BT; + break; + case RECORDING_CAM_MAIN: + gain_set_bits |= RECORDING_CAM_MAIN; + break; + case RECORDING_CAM_HP: + gain_set_bits |= RECORDING_CAM_HP; + break; + case RECORDING_CAM_BT: + gain_set_bits |= RECORDING_CAM_BT; + break; + case RECORDING_VC_MAIN: + gain_set_bits |= RECORDING_VC_MAIN; + break; + case RECORDING_VC_HP: + gain_set_bits |= RECORDING_VC_HP; + break; + case RECORDING_VC_BT: + gain_set_bits |= RECORDING_VC_BT; + break; + default: + pr_err("recording gain flag is wrong\n"); + } + + } + + DEBUG_LOG("Set gain mode = 0x%x, device = 0x%x, gain_bits = 0x%x,\ + table_num=%d, gain_code = %d\n", + mode, device, gain_set_bits, table_num, wm8994->gain_code); + + /* default gain table setting */ + for (i = 0; i < table_num; i++) { + if ((default_gain_table_p + i)->mode & gain_set_bits) { + val = wm8994_read(codec, (default_gain_table_p + i)->reg); + val &= ~((default_gain_table_p + i)->mask); + val |= (default_gain_table_p + i)->gain; + wm8994_write(codec, (default_gain_table_p + i)->reg, val); + } + } + + if (wm8994->gain_code) { + gain_set_bits &= ~(COMMON_SET_BIT); + + switch (wm8994->gain_code) { + case 1: + gain_set_bits |= (mode | GAIN_DIVISION_BIT_1); + break; + case 2: + gain_set_bits |= (mode | GAIN_DIVISION_BIT_2); + break; + case 3: + /* eur and eur tft device are same gain values currently + * but gain code is different because of modem. + */ + gain_set_bits |= (mode | GAIN_DIVISION_BIT_1); + break; + default: + DEBUG_LOG_ERR("gain_code(%d) isn't support", wm8994->gain_code); + return 0; + } + + default_gain_table_p = gain_code_table; + table_num = GAIN_CODE_NUM; + + for (i = 0; i < table_num; i++) { + if ((default_gain_table_p + i)->mode == gain_set_bits) { + val = wm8994_read(codec, (default_gain_table_p + i)->reg); + val &= ~((default_gain_table_p + i)->mask); + val |= (default_gain_table_p + i)->gain; + wm8994_write(codec, (default_gain_table_p + i)->reg, val); + } + } + + } + return 0; + +} + |