aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/codecs/wm8994_herring.c2629
-rwxr-xr-xsound/soc/codecs/wm8994_samsung.c1528
-rwxr-xr-xsound/soc/codecs/wm8994_samsung.h119
-rw-r--r--sound/soc/samsung/herring-wm8994.c2
4 files changed, 2799 insertions, 1479 deletions
diff --git a/sound/soc/codecs/wm8994_herring.c b/sound/soc/codecs/wm8994_herring.c
index 10be23c..73ef22d 100644
--- a/sound/soc/codecs/wm8994_herring.c
+++ b/sound/soc/codecs/wm8994_herring.c
@@ -1,5 +1,5 @@
/*
- * wm8994_aries.c -- WM8994 ALSA Soc Audio driver related Aries
+ * wm8994_crespo.c -- WM8994 ALSA Soc Audio driver related Aries
*
* Copyright (C) 2010 Samsung Electronics.
*
@@ -15,11 +15,11 @@
#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 <mach/gpio-crespo.h>
-#include "wm8994.h"
+#include "wm8994_samsung.h"
/*
* Debug Feature
@@ -36,244 +36,141 @@
/* DAC */
#define TUNING_DAC1L_VOL 0xC0 /* 610h */
#define TUNING_DAC1R_VOL 0xC0 /* 611h */
+#define TUNING_DAC2L_VOL 0xC0 /* 612h */
+#define TUNING_DAC2R_VOL 0xC0 /* 613h */
/* Speaker */
#define TUNING_SPKMIXL_ATTEN 0x0 /* 22h */
#define TUNING_SPKMIXR_ATTEN 0x0 /* 23h */
-#define TUNING_MP3_SPKL_VOL 0x3E /* 26h */
-#define TUNING_MP3_CLASSD_VOL 0x5 /* 25h */
-
-#define TUNING_FMRADIO_SPKL_VOL 0x3E /* 26h */
-#define TUNING_FMRADIO_CLASSD_VOL 0x5 /* 25h */
+/* Headset */
+#define TUNING_EAR_OUTMIX5_VOL 0x0 /* 31h */
+#define TUNING_EAR_OUTMIX6_VOL 0x0 /* 32h */
-#define TUNING_CALL_SPKL_VOL 0x3E /* 26h */
-#define TUNING_CALL_CLASSD_VOL 0x7 /* 25h */
+/*
+ * Normal
+ */
+/* Speaker */
+#define TUNING_MP3_SPKL_VOL 0x3E /*26h */
+#define TUNING_MP3_CLASSD_VOL 0x5 /* 25h */
/* Headset */
-#define TUNING_EAR_OUTMIX5_VOL 0x0 /* 31h */
-#define TUNING_EAR_OUTMIX6_VOL 0x0 /* 32h */
-
-#define TUNING_MP3_OUTPUTL_VOL 0x34 /* 1Ch */
-#define TUNING_MP3_OUTPUTR_VOL 0x34 /* 1Dh */
-#define TUNING_MP3_OPGAL_VOL 0x39 /* 20h */
-#define TUNING_MP3_OPGAR_VOL 0x39 /* 21h */
+#define TUNING_MP3_OUTPUTL_VOL 0x2F /* 1Ch */
+#define TUNING_MP3_OUTPUTR_VOL 0x2F /* 1Dh */
+#define TUNING_MP3_OPGAL_VOL 0x39 /* 20h */
+#define TUNING_MP3_OPGAR_VOL 0x39 /* 21h */
-#define TUNING_CALL_OUTPUTL_VOL 0x39 /* 1Ch */
-#define TUNING_CALL_OUTPUTR_VOL 0x39 /* 1Dh */
-#define TUNING_CALL_OPGAL_VOL 0x39 /* 20h */
-#define TUNING_CALL_OPGAR_VOL 0x39 /* 21h */
+/* Speaker_Headset */
+#define TUNING_MP3_DUAL_OUTPUTL_VOL 0x1E /* 1Ch */
+#define TUNING_MP3_DUAL_OUTPUTR_VOL 0x1E /* 1Dh */
-#define TUNING_FMRADIO_OUTPUTL_VOL 0x38 /* 1Ch */
-#define TUNING_FMRADIO_OUTPUTR_VOL 0x38 /* 1Dh */
-#define TUNING_FMRADIO_OPGAL_VOL 0x39 /* 20h */
-#define TUNING_FMRADIO_OPGAR_VOL 0x39 /* 21h */
+/*
+ * Ringtone
+ */
+/* Speaker */
+#define TUNING_RING_SPKL_VOL 0x3E /* 26h */
+#define TUNING_RING_CLASSD_VOL 0x5 /* 25h */
-#define TUNING_HPOUTMIX_VOL 0x0
+/* Headset */
+#define TUNING_RING_OUTPUTL_VOL 0x34 /* 1Ch */
+#define TUNING_RING_OUTPUTR_VOL 0x34 /* 1Dh */
+#define TUNING_RING_OPGAL_VOL 0x39 /* 20h */
+#define TUNING_RING_OPGAR_VOL 0x39 /* 21h */
/* Dual */
-#define TUNING_DUAL_OUTPUTL_VOL 0x1E /* 1Ch */
-#define TUNING_DUAL_OUTPUTR_VOL 0x1E /* 1Dh */
+#define TUNING_RING_DUAL_OUTPUTL_VOL 0x1E /* 1Ch */
+#define TUNING_RING_DUAL_OUTPUTR_VOL 0x1E /* 1Dh */
/*
- * Recording
+ * Call
*/
-/* Main MIC */
-#define TUNING_RECORD_MAIN_INPUTLINE_VOL 0x18 /* 18h */
+/* Speaker */
+#define TUNING_CALL_SPKL_VOL 0x35 /* 26h */
+#define TUNING_CALL_CLASSD_VOL 0x7 /* 25h */
-/* Ear MIC */
-#define TUNING_RECORD_SUB_INPUTMIX_VOL 0x17 /* 1Ah */
+/* Headset */
+#define TUNING_CALL_OUTPUTL_VOL 0x30 /* 1Ch */
+#define TUNING_CALL_OUTPUTR_VOL 0x30 /* 1Dh */
+#define TUNING_CALL_OPGAL_VOL 0x39 /* 20h */
+#define TUNING_CALL_OPGAR_VOL 0x39 /* 21h */
-/* Call Main MIC */
-#define TUNING_CALL_RCV_INPUTMIX_VOL 0x16 /* 18h */
-#define TUNING_CALL_SPK_INPUTMIX_VOL 0x17 /* 18h */
+/* Receiver */
+#define TUNING_RCV_OUTMIX5_VOL 0x0 /* 31h */
+#define TUNING_RCV_OUTMIX6_VOL 0x0 /* 32h */
+#define TUNING_RCV_OPGAL_VOL 0x3F /* 20h */
+#define TUNING_RCV_OPGAR_VOL 0x3F /* 21h */
+#define TUNING_HPOUT2_VOL 0x0 /* 1Fh */
-/* Ear MIC */
-#define TUNING_CALL_EAR_INPUTMIX_VOL 0x1F /* 1Ah */
+/* Call Main MIC */
+#define TUNING_CALL_RCV_INPUTMIX_VOL 0x17 /* 18h */
+#define TUNING_CALL_RCV_MIXER_VOL WM8994_IN1L_MIXINL_VOL /* 29h */
-/* Receiver */
-#define TUNING_RCV_OUTMIX5_VOL 0x0 /* 31h */
-#define TUNING_RCV_OUTMIX6_VOL 0x0 /* 32h */
-#define TUNING_RCV_OPGAL_VOL 0x3D /* 20h */
-#define TUNING_RCV_OPGAR_VOL 0x3D /* 21h */
-#define TUNING_HPOUT2_VOL 0x0 /* 1Fh */
+#define TUNING_CALL_SPK_INPUTMIX_VOL 0x11 /* 18h */
+#define TUNING_CALL_SPK_MIXER_VOL WM8994_IN1L_MIXINL_VOL /* 29h */
-int audio_init(void)
-{
+/* Call Ear MIC */
+#define TUNING_CALL_EAR_INPUTMIX_VOL 0x1D /* 1Ah */
- /* CODEC LDO SETTING */
- if (gpio_is_valid(GPIO_CODEC_LDO_EN)) {
- if (gpio_request(GPIO_CODEC_LDO_EN, "CODEC_LDO_EN"))
- DEBUG_LOG_ERR("Failed to request CODEC_LDO_EN!\n");
- gpio_direction_output(GPIO_CODEC_LDO_EN, 0);
- }
+/*Input */
+#define TUNING_DAC1L_RADIO_VOL 0xA8 /* 402h */
+#define TUNING_DAC1R_RADIO_VOL 0xA8 /* 403h */
- s3c_gpio_setpull(GPIO_CODEC_LDO_EN, S3C_GPIO_PULL_NONE);
+/* Dual */
+#define TUNING_DUAL_DAC1L_RADIO_VOL 0x70 /* 402h */
+#define TUNING_DUAL_DAC1R_RADIO_VOL 0x70 /* 403h */
- /* CODEC XTAL CLK SETTING */
-#if (defined CONFIG_JUPITER_VER_B5) || (defined CONFIG_ARIES_VER_B0) || \
- (defined CONFIG_MACH_S5PC110_ARIES)
- if (gpio_is_valid(GPIO_CODEC_XTAL_EN)) {
- if (gpio_request(GPIO_CODEC_XTAL_EN, "GPIO_CODEC_XTAL_EN"))
- DEBUG_LOG_ERR
- ("Failed to request GPIO_CODEC_XTAL_EN!\n");
+/*
+ * Recording
+ */
+/* Main MIC */
+#define TUNING_RECORD_MAIN_INPUTLINE_VOL 0x18 /* 18h */
+#define TUNING_RECORD_MAIN_AIF1ADCL_VOL 0xC0 /* 400h */
+#define TUNING_RECORD_MAIN_AIF1ADCR_VOL 0xC0 /* 401h */
- gpio_direction_output(GPIO_CODEC_XTAL_EN, 0);
- }
- s3c_gpio_setpull(GPIO_CODEC_XTAL_EN, S3C_GPIO_PULL_NONE);
-#endif
- if (gpio_is_valid(GPIO_MICBIAS_EN)) {
- if (gpio_request(GPIO_MICBIAS_EN, "GPJ4"))
- pr_err("Failed to request GPIO_MICBIAS_EN!\n");
- gpio_direction_output(GPIO_MICBIAS_EN, 0);
- }
- s3c_gpio_setpull(GPIO_MICBIAS_EN, S3C_GPIO_PULL_NONE);
-
- /* For preserving output of codec related pins. */
- s3c_gpio_slp_cfgpin(GPIO_CODEC_LDO_EN, S3C_GPIO_SLP_PREV);
- s3c_gpio_slp_setpull_updown(GPIO_CODEC_LDO_EN, S3C_GPIO_PULL_NONE);
- s3c_gpio_slp_cfgpin(GPIO_MICBIAS_EN, S3C_GPIO_SLP_PREV);
- s3c_gpio_slp_setpull_updown(GPIO_MICBIAS_EN, S3C_GPIO_PULL_NONE);
- /* PCM_SEL Setting */
-#if (defined CONFIG_JUPITER_VER_B5) || (defined CONFIG_ARIES_VER_B0) || \
- (defined CONFIG_ARIES_VER_B1) || (defined CONFIG_MACH_S5PC110_ARIES)
- s3c_gpio_slp_cfgpin(GPIO_EARPATH_SEL, S3C_GPIO_SLP_PREV);
- s3c_gpio_slp_setpull_updown(GPIO_EARPATH_SEL, S3C_GPIO_PULL_NONE);
-#endif
-
-#if (defined CONFIG_JUPITER_VER_B5) || (defined CONFIG_ARIES_VER_B0) || \
- (defined CONFIG_MACH_S5PC110_ARIES)
- s3c_gpio_slp_setpull_updown(GPIO_CODEC_XTAL_EN, S3C_GPIO_PULL_NONE);
-#endif
+#define TUNING_RECOGNITION_MAIN_INPUTLINE_VOL 0x1C /* 18h */
+#define TUNING_RECOGNITION_MAIN_AIF1ADCL_VOL 0xD0 /* 400h */
+#define TUNING_RECOGNITION_MAIN_AIF1ADCR_VOL 0xD0 /* 401h */
- return 0;
+/* Ear MIC */
+#define TUNING_RECORD_SUB_INPUTMIX_VOL 0x15 /* 1Ah */
+#define TUNING_RECORD_SUB_AIF1ADCL_VOL 0xC0 /* 400h */
+#define TUNING_RECORD_SUB_AIF1ADCR_VOL 0xC0 /* 401h */
-}
+#define TUNING_RECOGNITION_SUB_INPUTMIX_VOL 0x10 /* 1Ah */
+#define TUNING_RECOGNITION_SUB_AIF1ADCL_VOL 0xC0 /* 400h */
+#define TUNING_RECOGNITION_SUB_AIF1ADCR_VOL 0xC0 /* 401h */
-int audio_power(int en)
+/* S5P_SLEEP_CONFIG must be controlled by codec if codec use XUSBTI */
+int wm8994_configure_clock(struct snd_soc_codec *codec, int en)
{
-#if (defined CONFIG_JUPITER_VER_B4)
- u32 val;
-
- DEBUG_LOG("LDO Enable = %d, XTAL CLK From AP EMUL", en);
- val = __raw_readl(S5P_CLK_OUT);
- val &= 0xFFFE0FFF;
-#endif
+ struct wm8994_priv *wm8994 = codec->drvdata;
if (en) {
- /* Turn on LDO for codec.*/
- gpio_set_value(GPIO_CODEC_LDO_EN, 1);
-
- /* wait for warming up */
- /* commenting sleep as not required in SLSI platform */
- /* msleep(10);*/
-
- /* Turn on master clock.*/
-#if (defined CONFIG_JUPITER_VER_B5) || (defined CONFIG_ARIES_VER_B0) || \
- (defined CONFIG_ARIES_VER_B1) || \
- (defined CONFIG_ARIES_VER_B2) || \
- (defined CONFIG_ARIES_VER_B3) || \
- (defined CONFIG_MACH_S5PC110_P1) || \
- (defined CONFIG_MACH_S5PC110_ARIES) || \
- (defined CONFIG_MACH_S5PC110_CRESPO)
- DEBUG_LOG("LDO Enable = %d, XTAL CLK From OSI", en);
-#ifdef CONFIG_MACH_S5PC110_ARIES
- gpio_set_value(GPIO_CODEC_XTAL_EN, 1);
-#if (defined CONFIG_SND_S5P_WM8994_MASTER)
- else
- __raw_writel(__raw_readl(S5P_OTHERS) | (3 << 8),
- S5P_OTHERS);
-#endif
-#else
-#if (defined CONFIG_SND_S5P_WM8994_MASTER)
- __raw_writel(__raw_readl(S5P_OTHERS) | (3 << 8), S5P_OTHERS);
-#endif
-#endif
-#elif (defined CONFIG_JUPITER_VER_B4)
-#ifdef CONFIG_SND_S5P_WM8994_MASTER
- val |= (0x11 << 12);
-#else
- val |= (0x02 << 12);
- val |= (0x5 << 20);
-#endif /* end of CONFIG_SND_S5P_WM8994_MASTER */
- __raw_writel(val, S5P_CLK_OUT);
-#endif /* end of CONFIG_JUPITER_VER_05 */
+ clk_enable(wm8994->codec_clk);
+ DEBUG_LOG("USBOSC Enabled in Sleep Mode\n");
} else {
- /* Turn off LDO for codec. */
- gpio_set_value(GPIO_CODEC_LDO_EN, 0);
-
- /* wait to turn off codec entirely */
- /* commenting sleep as not required in SLSI platform */
- /*msleep(125);*/
-
- /* Turn on master clock.*/
-#if (defined CONFIG_JUPITER_VER_B5)
- DEBUG_LOG("LDO Disable = %d, XTAL CLK From OSI", en);
- gpio_set_value(GPIO_CODEC_XTAL_EN, 0);
-#elif (defined CONFIG_JUPITER_VER_B4)
- DEBUG_LOG("LDO Disable = %d, XTAL CLK From AP EMUL", en);
-#ifdef CONFIG_SND_S5P_WM8994_MASTER
- val &= ~(0x11 << 12);
-#else
- val &= ~(0x02 << 12);
- val &= ~(0x5 << 20);
-#endif /* end of CONFIG_SND_S5P_WM8994_MASTER*/
-#elif (defined CONFIG_ARIES_VER_B0) || (defined CONFIG_ARIES_VER_B1) || \
- (defined CONFIG_ARIES_VER_B2) || \
- (defined CONFIG_ARIES_VER_B3) || \
- (defined CONFIG_MACH_S5PC110_P1) || \
- (defined CONFIG_MACH_S5PC110_ARIES) || \
- (defined CONFIG_MACH_S5PC110_CRESPO)
-#ifdef CONFIG_MACH_S5PC110_ARIES
- gpio_set_value(GPIO_CODEC_XTAL_EN, 0);
-#if (defined CONFIG_SND_S5P_WM8994_MASTER)
- else {
- __raw_writel(__raw_readl(S5P_OTHERS) & (~(0x3 << 8)),
- S5P_OTHERS);
- __raw_writel(__raw_readl(S5P_CLK_OUT) & (0xFFFFFFFE),
- S5P_CLK_OUT);
- }
-#endif
-#else
-#if (defined CONFIG_SND_S5P_WM8994_MASTER)
- __raw_writel(__raw_readl(S5P_OTHERS) & (~(0x3 << 8)),
- S5P_OTHERS);
- __raw_writel(__raw_readl(S5P_CLK_OUT) & (0xFFFFFFFE),
- S5P_CLK_OUT);
-#endif
-#endif
-#else
-#if (defined CONFIG_JUPITER_VER_B4)
- __raw_writel(val, S5P_CLK_OUT);
-#endif
-#endif
+ clk_disable(wm8994->codec_clk);
+ DEBUG_LOG("USBOSC disable in Sleep Mode\n");
}
- DEBUG_LOG("AUDIO POWER COMPLETED : %d", en);
-
return 0;
}
-void audio_ctrl_mic_bias_gpio(int enable)
+void audio_ctrl_mic_bias_gpio(struct wm8994_platform_data *pdata, int enable)
{
- int headset_state;
-
DEBUG_LOG("enable = [%d]", enable);
- if (enable) {
- /* commented as this function is not present in SLSI platform */
- /* set_recording_status(1); */
- gpio_set_value(GPIO_MICBIAS_EN, 1);
- } else {
- /* commented as this function is not present in SLSI platform */
- /* set_recording_status(0);*/
- /* headset_state = get_headset_status();*/
-/* if( headset_state == 0 ||headset_state == 0x1 << 5 ) */
- gpio_set_value(GPIO_MICBIAS_EN, 0);
+ if (!pdata)
+ pr_err("failed to turn off micbias pin\n");
+ else {
+ if (enable)
+ gpio_set_value(pdata->micbias, 1);
+ else
+ gpio_set_value(pdata->micbias, 0);
}
}
-/*Audio Routing routines for the universal board..wm8994 codec*/
+/* Audio Routing routines for the universal board..wm8994 codec*/
void wm8994_disable_playback_path(struct snd_soc_codec *codec,
enum audio_path path)
{
@@ -315,7 +212,7 @@ void wm8994_disable_playback_path(struct snd_soc_codec *codec,
break;
case SPK:
- /*Disbale the SPKOUTL */
+ /* Disbale the SPKOUTL */
val &= ~(WM8994_SPKOUTL_ENA_MASK);
wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val);
@@ -331,7 +228,7 @@ void wm8994_disable_playback_path(struct snd_soc_codec *codec,
WM8994_SPKMIXR_TO_SPKOUTR_MASK);
wm8994_write(codec, WM8994_SPKOUT_MIXERS, val);
- /*Mute Speaker mixer */
+ /* Mute Speaker mixer */
val = wm8994_read(codec, WM8994_SPEAKER_MIXER);
val &= ~(WM8994_DAC1L_TO_SPKMIXL_MASK);
wm8994_write(codec, WM8994_SPEAKER_MIXER, val);
@@ -374,12 +271,25 @@ void wm8994_disable_playback_path(struct snd_soc_codec *codec,
wm8994_write(codec, WM8994_CHARGE_PUMP_1, 0x1F25);
break;
+ case BT:
+ val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_6);
+ val &= ~(WM8994_AIF3_ADCDAT_SRC_MASK |
+ WM8994_AIF2_ADCDAT_SRC_MASK |
+ WM8994_AIF2_DACDAT_SRC_MASK |
+ WM8994_AIF1_DACDAT_SRC_MASK);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_6, val);
+
+ 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);
- /* ------------------ Ear path setting ------------------ */
/* Disable DAC1L to HPOUT1L path */
val = wm8994_read(codec, WM8994_OUTPUT_MIXER_1);
val &= ~(WM8994_DAC1L_TO_HPOUT1L_MASK |
@@ -392,10 +302,10 @@ void wm8994_disable_playback_path(struct snd_soc_codec *codec,
WM8994_DAC1R_TO_MIXOUTR_MASK);
wm8994_write(codec, WM8994_OUTPUT_MIXER_2, val);
- /*Disable Charge Pump */
+ /* Disable Charge Pump */
val = wm8994_read(codec, WM8994_CHARGE_PUMP_1);
val &= ~WM8994_CP_ENA_MASK;
- val |= WM8994_CP_ENA_DEFAULT; /* this is from wolfson */
+ val |= WM8994_CP_ENA_DEFAULT;
wm8994_write(codec, WM8994_CHARGE_PUMP_1, val);
/* Intermediate HP settings */
@@ -405,7 +315,6 @@ void wm8994_disable_playback_path(struct snd_soc_codec *codec,
WM8994_HPOUT1L_OUTP_MASK | WM8994_HPOUT1L_RMV_SHORT_MASK);
wm8994_write(codec, WM8994_ANALOGUE_HP_1, val);
- /* ------------------ Spk path setting ------------------ */
/* Disable SPKLVOL */
val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_3);
val &= ~(WM8994_SPKLVOL_ENA_MASK);
@@ -418,7 +327,7 @@ void wm8994_disable_playback_path(struct snd_soc_codec *codec,
WM8994_SPKMIXR_TO_SPKOUTR_MASK);
wm8994_write(codec, WM8994_SPKOUT_MIXERS, val);
- /*Mute Speaker mixer */
+ /* Mute Speaker mixer */
val = wm8994_read(codec, WM8994_SPEAKER_MIXER);
val &= ~(WM8994_DAC1L_TO_SPKMIXL_MASK);
wm8994_write(codec, WM8994_SPEAKER_MIXER, val);
@@ -431,21 +340,19 @@ void wm8994_disable_playback_path(struct snd_soc_codec *codec,
}
}
-void wm8994_disable_rec_path(struct snd_soc_codec *codec,
- enum mic_path rec_path)
+void wm8994_disable_rec_path(struct snd_soc_codec *codec)
{
struct wm8994_priv *wm8994 = codec->drvdata;
u16 val;
+ enum mic_path mic = wm8994->rec_path;
wm8994->rec_path = MIC_OFF;
- audio_ctrl_mic_bias_gpio(0);
- val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1);
- val &= ~(WM8994_MICB1_ENA_MASK);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val);
+ if (!(wm8994->call_state & DISCONNECT))
+ audio_ctrl_mic_bias_gpio(wm8994->pdata, 0);
- switch (rec_path) {
+ switch (mic) {
case MAIN:
DEBUG_LOG("Disabling MAIN Mic Path..\n");
@@ -453,35 +360,34 @@ void wm8994_disable_rec_path(struct snd_soc_codec *codec,
val &= ~(WM8994_IN1L_ENA_MASK | WM8994_MIXINL_ENA_MASK);
wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, val);
- if (!wm8994->testmode_config_flag) {
- /* 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 */
+ /* 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 */
+ /* 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 */
+ /* Disable timeslots */
val = wm8994_read(codec, WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING);
- val |= WM8994_ADC1L_TO_AIF1ADC1L;
+ val &= ~(WM8994_ADC1L_TO_AIF1ADC1L);
wm8994_write(codec, WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING, val);
break;
@@ -491,22 +397,21 @@ void wm8994_disable_rec_path(struct snd_soc_codec *codec,
val &= ~(WM8994_IN1R_ENA_MASK | WM8994_MIXINR_ENA_MASK);
wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, val);
- if (!wm8994->testmode_config_flag) {
- /* 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);
- }
+ /* 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);
@@ -524,296 +429,126 @@ void wm8994_disable_rec_path(struct snd_soc_codec *codec,
wm8994_write(codec, WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING, val);
break;
+ case BT_REC:
+ 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;
+
default:
- DEBUG_LOG_ERR("Path[%d] is not invaild!\n", rec_path);
+ DEBUG_LOG_ERR("Path[%d] is not invaild!\n", mic);
break;
}
}
-void wm8994_disable_fmradio_path(struct snd_soc_codec *codec,
- enum fmradio_audio_path path)
+void wm8994_record_headset_mic(struct snd_soc_codec *codec)
{
struct wm8994_priv *wm8994 = codec->drvdata;
u16 val;
- DEBUG_LOG("Turn off fmradio_path = [%d]", path);
-
- switch (path) {
- case FMR_OFF:
- wm8994->fmradio_path = FMR_OFF;
-
- /* Disable speaker setting for FM radio */
- /* disbale the SPKOUTL */
- val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1);
- val &= ~(WM8994_SPKOUTL_ENA_MASK);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val);
-
- /* Disable SPK Volume. */
- val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_3);
- val &= ~(WM8994_SPKRVOL_ENA_MASK | WM8994_SPKLVOL_ENA_MASK);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, val);
-
- if (!wm8994->testmode_config_flag) {
- /* Mute the SPKMIXVOLUME */
- val = wm8994_read(codec, WM8994_SPKMIXL_ATTENUATION);
- val &= ~(WM8994_SPKMIXL_VOL_MASK);
- wm8994_write(codec, WM8994_SPKMIXL_ATTENUATION, val);
-
- val = wm8994_read(codec, WM8994_SPKMIXR_ATTENUATION);
- val &= ~(WM8994_SPKMIXR_VOL_MASK);
- wm8994_write(codec, WM8994_SPKMIXR_ATTENUATION, val);
-
- val = wm8994_read(codec, WM8994_SPEAKER_VOLUME_LEFT);
- val &= ~(WM8994_SPKOUTL_MUTE_N_MASK |
- WM8994_SPKOUTL_VOL_MASK);
- 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_CLASSD);
- val &= ~(WM8994_SPKOUTL_BOOST_MASK);
- wm8994_write(codec, WM8994_CLASSD, val);
- }
-
- /*Output MIxer-Output PGA */
- 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);
-
- /* Output mixer setting */
- val = wm8994_read(codec, WM8994_SPEAKER_MIXER);
- val &= ~(WM8994_MIXINL_TO_SPKMIXL_MASK |
- WM8994_MIXINR_TO_SPKMIXR_MASK);
- wm8994_write(codec, WM8994_SPEAKER_MIXER, val);
-
- /* Disable earpath setting for FM radio */
- /* Disable end point for preventing pop up noise. */
- val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1);
- val &= ~(WM8994_HPOUT1L_ENA_MASK | WM8994_HPOUT1R_ENA_MASK);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val);
-
- /* Disable MIXOUT */
- 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);
-
- if (!wm8994->testmode_config_flag) {
- /* Output setting */
- val = wm8994_read(codec, WM8994_LEFT_OUTPUT_VOLUME);
- val &= ~(WM8994_HPOUT1L_MUTE_N_MASK |
- WM8994_HPOUT1L_VOL_MASK);
- wm8994_write(codec, WM8994_LEFT_OUTPUT_VOLUME, val);
-
- val = wm8994_read(codec, WM8994_RIGHT_OUTPUT_VOLUME);
- val &= ~(WM8994_HPOUT1R_MUTE_N_MASK |
- WM8994_HPOUT1R_VOL_MASK);
- wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, val);
- }
- /*Disable Charge Pump */
- val = wm8994_read(codec, WM8994_CHARGE_PUMP_1);
- val &= ~WM8994_CP_ENA_MASK;
- val |= WM8994_CP_ENA_DEFAULT; /* this is from wolfson */
- 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 Output mixer setting */
- val = wm8994_read(codec, WM8994_OUTPUT_MIXER_1);
- val &= ~(WM8994_DAC1L_TO_HPOUT1L_MASK |
- WM8994_MIXINL_TO_MIXOUTL_MASK);
- wm8994_write(codec, WM8994_OUTPUT_MIXER_1, val);
-
- val = wm8994_read(codec, WM8994_OUTPUT_MIXER_2);
- val &= ~(WM8994_DAC1R_TO_HPOUT1R_MASK |
- WM8994_MIXINR_TO_MIXOUTR_MASK);
- wm8994_write(codec, WM8994_OUTPUT_MIXER_2, val);
-
- /* Disable common setting for FM radio */
- /* Disable IN2 and MIXIN */
- val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_2);
- val &= ~(WM8994_TSHUT_ENA_MASK | WM8994_TSHUT_OPDIS_MASK |
- WM8994_OPCLK_ENA_MASK | WM8994_MIXINL_ENA_MASK |
- WM8994_MIXINR_ENA_MASK | WM8994_IN2L_ENA_MASK |
- WM8994_IN2R_ENA_MASK);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, val);
-
- /* Disable Input mixer setting */
- val = wm8994_read(codec, WM8994_INPUT_MIXER_2);
- val &= ~(WM8994_IN2LN_TO_IN2L_MASK | WM8994_IN2RN_TO_IN2R_MASK);
- wm8994_write(codec, WM8994_INPUT_MIXER_2, val);
-
- if (!wm8994->testmode_config_flag) {
- /* Disable IN2L to MIXINL */
- val = wm8994_read(codec, WM8994_INPUT_MIXER_3);
- val &= ~(WM8994_IN2L_TO_MIXINL_MASK);
- wm8994_write(codec, WM8994_INPUT_MIXER_3, val);
-
- /*Disable IN2R to MIXINR */
- val = wm8994_read(codec, WM8994_INPUT_MIXER_4);
- val &= ~(WM8994_IN2R_TO_MIXINR_MASK);
- wm8994_write(codec, WM8994_INPUT_MIXER_4, val);
- }
- /* Mute IN2L PGA volume */
- val = wm8994_read(codec, WM8994_LEFT_LINE_INPUT_3_4_VOLUME);
- val &= ~(WM8994_IN2L_VU_MASK | WM8994_IN2L_MUTE_MASK |
- WM8994_IN2L_VOL_MASK);
- val |= (WM8994_IN2L_VU | WM8994_IN2L_MUTE);
- wm8994_write(codec, WM8994_LEFT_LINE_INPUT_3_4_VOLUME, val);
-
- val = wm8994_read(codec, WM8994_RIGHT_LINE_INPUT_3_4_VOLUME);
- val &= ~(WM8994_IN2R_VU_MASK | WM8994_IN2R_MUTE_MASK |
- WM8994_IN2R_VOL_MASK);
- val |= (WM8994_IN2R_VU | WM8994_IN2R_MUTE);
- wm8994_write(codec, WM8994_RIGHT_LINE_INPUT_3_4_VOLUME, val);
-
- /* Disable path setting for mixing */
- val = wm8994_read(codec, WM8994_SPEAKER_MIXER);
- val &= ~(WM8994_DAC1L_TO_SPKMIXL_MASK);
- wm8994_write(codec, WM8994_SPEAKER_MIXER, 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);
- break;
-
- case FMR_SPK:
- /* Output mixer setting */
- val = wm8994_read(codec, WM8994_SPEAKER_MIXER);
- val &= ~(WM8994_MIXINL_TO_SPKMIXL_MASK |
- WM8994_MIXINR_TO_SPKMIXR_MASK);
- wm8994_write(codec, WM8994_SPEAKER_MIXER, val);
- break;
-
- case FMR_HP:
- /* Disable end point for preventing pop up noise. */
- /* Disable Output mixer setting */
- val = wm8994_read(codec, WM8994_OUTPUT_MIXER_1);
- val &= ~(WM8994_DAC1L_TO_HPOUT1L_MASK |
- WM8994_MIXINL_TO_MIXOUTL_MASK);
- wm8994_write(codec, WM8994_OUTPUT_MIXER_1, val);
-
- val = wm8994_read(codec, WM8994_OUTPUT_MIXER_2);
- val &= ~(WM8994_DAC1R_TO_HPOUT1R_MASK |
- WM8994_MIXINR_TO_MIXOUTR_MASK);
- wm8994_write(codec, WM8994_OUTPUT_MIXER_2, val);
- break;
-
- case FMR_SPK_MIX:
- /*Mute the DAC path */
- val = wm8994_read(codec, WM8994_SPEAKER_MIXER);
- val &= ~(WM8994_DAC1L_TO_SPKMIXL_MASK);
- wm8994_write(codec, WM8994_SPEAKER_MIXER, val);
- break;
-
- case FMR_HP_MIX:
- /* 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);
+ audio_ctrl_mic_bias_gpio(wm8994->pdata, 1);
- /* 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);
- break;
-
- case FMR_SPK_HP_MIX:
- /*Mute the DAC path */
- val = wm8994_read(codec, WM8994_SPEAKER_MIXER);
- val &= ~(WM8994_DAC1L_TO_SPKMIXL_MASK);
- wm8994_write(codec, WM8994_SPEAKER_MIXER, val);
+ DEBUG_LOG("Recording through Headset Mic\n");
- /* 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);
+ val = wm8994_read(codec, WM8994_SPEAKER_MIXER);
+ val &= ~WM8994_MIXINL_TO_SPKMIXL_MASK;
+ wm8994_write(codec, WM8994_SPEAKER_MIXER, 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);
- break;
+ val = wm8994_read(codec, WM8994_OUTPUT_MIXER_1);
+ val &= ~WM8994_MIXINL_TO_MIXOUTL_MASK;
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_1, val);
- default:
- DEBUG_LOG_ERR("fmradio path[%d] is not invaild!\n", path);
- return;
- break;
- }
-}
+ val = wm8994_read(codec, WM8994_OUTPUT_MIXER_2);
+ val &= ~WM8994_MIXINR_TO_MIXOUTR_MASK;
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_2, val);
-void wm8994_record_headset_mic(struct snd_soc_codec *codec)
-{
- struct wm8994_priv *wm8994 = codec->drvdata;
+ val = wm8994_read(codec, WM8994_DAC2_LEFT_MIXER_ROUTING);
+ val &= ~(WM8994_ADC1_TO_DAC2L_MASK);
+ wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING, val);
- u16 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);
- audio_ctrl_mic_bias_gpio(1);
+ /* 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);
- DEBUG_LOG("Recording through Headset Mic\n");
+ wm8994_write(codec, WM8994_ANTIPOP_2, 0x68);
- /*Enable mic bias, vmid, bias generator */
+ /* Enable mic bias, vmid, bias generator */
val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1);
- val &= ~(WM8994_BIAS_ENA_MASK | WM8994_VMID_SEL_MASK |
- WM8994_MICB1_ENA_MASK);
- val |= (WM8994_BIAS_ENA | WM8994_VMID_SEL_NORMAL | WM8994_MICB1_ENA);
+ 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_MIXINR_ENA | WM8994_IN1R_ENA);
wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, val);
- if (!wm8994->testmode_config_flag) {
- /* Enable 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 | TUNING_RECORD_SUB_INPUTMIX_VOL);
- wm8994_write(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, val);
-
- /* unmute 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);
- val |= (WM8994_IN1R_TO_MIXINR); /* 0db */
- wm8994_write(codec, WM8994_INPUT_MIXER_4, val);
- }
+ val = wm8994_read(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME);
+ val &= ~(WM8994_IN1R_MUTE_MASK | WM8994_IN1R_VOL_MASK);
+ if (wm8994->recognition_active == REC_ON)
+ val |= (WM8994_IN1R_VU |
+ TUNING_RECOGNITION_SUB_INPUTMIX_VOL);
+ else
+ val |= (WM8994_IN1R_VU | TUNING_RECORD_SUB_INPUTMIX_VOL);
+ 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 |
+ WM8994_IN1R_MIXINR_VOL_MASK |
+ WM8994_MIXOUTR_MIXINR_VOL_MASK);
+ if (wm8994->recognition_active == REC_ON)
+ val |= (WM8994_IN1R_TO_MIXINR | WM8994_IN1R_MIXINR_VOL);
+ else
+ val |= (WM8994_IN1R_TO_MIXINR | WM8994_IN1R_MIXINR_VOL);
+ wm8994_write(codec, WM8994_INPUT_MIXER_4 , val);
+
+ val = wm8994_read(codec, WM8994_AIF1_ADC1_LEFT_VOLUME);
+ val &= ~(WM8994_AIF1ADC1L_VOL_MASK);
+ if (wm8994->recognition_active == REC_ON)
+ val |= (WM8994_AIF1ADC1_VU |
+ TUNING_RECOGNITION_SUB_AIF1ADCL_VOL);
+ else
+ val |= (WM8994_AIF1ADC1_VU | TUNING_RECORD_SUB_AIF1ADCL_VOL);
+ wm8994_write(codec, WM8994_AIF1_ADC1_LEFT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_AIF1_ADC1_RIGHT_VOLUME);
+ val &= ~(WM8994_AIF1ADC1R_VOL_MASK);
+
+ if (wm8994->recognition_active == REC_ON)
+ val |= (WM8994_AIF1ADC1_VU |
+ TUNING_RECOGNITION_SUB_AIF1ADCR_VOL);
+ else
+ val |= (WM8994_AIF1ADC1_VU |
+ TUNING_RECORD_SUB_AIF1ADCR_VOL);
+ wm8994_write(codec, WM8994_AIF1_ADC1_RIGHT_VOLUME, val);
val = (WM8994_IN1RN_TO_IN1R | WM8994_IN1RP_TO_IN1R);
wm8994_write(codec, WM8994_INPUT_MIXER_2, val);
- /*Digital Paths */
- /*Enable right ADC and time slot */
+ /* 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 */
+ /* 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;
@@ -833,46 +568,95 @@ void wm8994_record_main_mic(struct snd_soc_codec *codec)
u16 val;
DEBUG_LOG("Recording through Main Mic\n");
- /* audio_ctrl_mic_bias_gpio(1); */
+ audio_ctrl_mic_bias_gpio(wm8994->pdata, 1);
+
+ 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);
+
+ val = wm8994_read(codec, WM8994_AIF1_CONTROL_1);
+ val &= ~(WM8994_AIF1ADCL_SRC_MASK | WM8994_AIF1ADCR_SRC_MASK);
+ wm8994_write(codec, WM8994_AIF1_CONTROL_1, val);
+
+ /* Main mic volume issue fix: requested H/W */
+ wm8994_write(codec, WM8994_ANTIPOP_2, 0x68);
- /*Enable micbias,vmid,mic1 */
val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1);
- val &= ~(WM8994_BIAS_ENA_MASK | WM8994_VMID_SEL_MASK |
- WM8994_MICB1_ENA_MASK);
- val |= (WM8994_BIAS_ENA | WM8994_VMID_SEL_NORMAL | WM8994_MICB1_ENA);
+ 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_MIXINL_ENA | WM8994_IN1L_ENA);
wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, val);
- if (!wm8994->testmode_config_flag) {
- /* Unmute 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 | TUNING_RECORD_MAIN_INPUTLINE_VOL);
- wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME, val);
+ if (wm8994->recognition_active == REC_ON) {
+ val = wm8994_read(codec, WM8994_AIF1_ADC1_FILTERS);
+ val &= ~(WM8994_AIF1ADC1L_HPF_MASK | WM8994_AIF1ADC1R_HPF_MASK);
+ val |= (WM8994_AIF1ADC1L_HPF | WM8994_AIF1ADC1R_HPF);
+ wm8994_write(codec, WM8994_AIF1_ADC1_FILTERS, val);
+ }
- /*Unmute 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);
+ val = wm8994_read(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME);
+ val &= ~(WM8994_IN1L_MUTE_MASK | WM8994_IN1L_VOL_MASK);
+ if (wm8994->recognition_active == REC_ON)
+ val |= (WM8994_IN1L_VU |
+ TUNING_RECOGNITION_MAIN_INPUTLINE_VOL);
+ else
+ val |= (WM8994_IN1L_VU | TUNING_RECORD_MAIN_INPUTLINE_VOL);
+ 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 |
+ WM8994_IN1L_MIXINL_VOL_MASK |
+ WM8994_MIXOUTL_MIXINL_VOL_MASK);
+ if (wm8994->recognition_active == REC_ON)
+ val |= (WM8994_IN1L_TO_MIXINL);
+ else
val |= (WM8994_IN1L_MIXINL_VOL | WM8994_IN1L_TO_MIXINL);
- wm8994_write(codec, WM8994_INPUT_MIXER_3, val);
- }
+ wm8994_write(codec, WM8994_INPUT_MIXER_3, val);
- val = wm8994_read(codec, WM8994_INPUT_MIXER_2);
- val &= (WM8994_IN1LN_TO_IN1L_MASK | WM8994_IN1LP_TO_IN1L_MASK);
- val |= (WM8994_IN1LP_TO_IN1L | WM8994_IN1LN_TO_IN1L);
+ val = (WM8994_IN1LP_TO_IN1L | WM8994_IN1LN_TO_IN1L);
wm8994_write(codec, WM8994_INPUT_MIXER_2, val);
- /*Digital Paths */
+ val = wm8994_read(codec, WM8994_AIF1_ADC1_LEFT_VOLUME);
+ val &= ~(WM8994_AIF1ADC1L_VOL_MASK);
+ if (wm8994->recognition_active == REC_ON)
+ val |= (WM8994_AIF1ADC1_VU |
+ TUNING_RECOGNITION_MAIN_AIF1ADCL_VOL);
+ else
+ val |= (WM8994_AIF1ADC1_VU | TUNING_RECORD_MAIN_AIF1ADCL_VOL);
+ wm8994_write(codec, WM8994_AIF1_ADC1_LEFT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_AIF1_ADC1_RIGHT_VOLUME);
+ val &= ~(WM8994_AIF1ADC1R_VOL_MASK);
+ if (wm8994->recognition_active == REC_ON)
+ val |= (WM8994_AIF1ADC1_VU |
+ TUNING_RECOGNITION_MAIN_AIF1ADCR_VOL);
+ else
+ val |= (WM8994_AIF1ADC1_VU | TUNING_RECORD_MAIN_AIF1ADCR_VOL);
+ wm8994_write(codec, WM8994_AIF1_ADC1_RIGHT_VOLUME, 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 */
+ /* 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);
@@ -882,56 +666,127 @@ void wm8994_record_main_mic(struct snd_soc_codec *codec)
wm8994_write(codec, WM8994_AIF1_MASTER_SLAVE, val);
wm8994_write(codec, WM8994_GPIO_1, 0xA101);
+ if (wm8994->recognition_active == REC_ON)
+ msleep(60);
}
-void wm8994_set_playback_receiver(struct snd_soc_codec *codec)
+void wm8994_record_bluetooth(struct snd_soc_codec *codec)
{
- struct wm8994_priv *wm8994 = codec->drvdata;
+ u16 val;
+
+ DEBUG_LOG("BT Record Path for Voice Command\n");
+
+ wm8994_set_voicecall_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("");
- if (!wm8994->testmode_config_flag) {
- val = wm8994_read(codec, WM8994_OUTPUT_MIXER_5);
- val &= ~(WM8994_DACL_MIXOUTL_VOL_MASK);
- val |= TUNING_RCV_OUTMIX5_VOL << WM8994_DACL_MIXOUTL_VOL_SHIFT;
- wm8994_write(codec, WM8994_OUTPUT_MIXER_5, val);
+ val = wm8994_read(codec, WM8994_OUTPUT_MIXER_5);
+ val &= ~(WM8994_DACL_MIXOUTL_VOL_MASK);
+ val |= TUNING_RCV_OUTMIX5_VOL << WM8994_DACL_MIXOUTL_VOL_SHIFT;
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_5, val);
- val = wm8994_read(codec, WM8994_OUTPUT_MIXER_6);
- val &= ~(WM8994_DACR_MIXOUTR_VOL_MASK);
- val |= TUNING_RCV_OUTMIX6_VOL << WM8994_DACR_MIXOUTR_VOL_SHIFT;
- wm8994_write(codec, WM8994_OUTPUT_MIXER_6, val);
+ val = wm8994_read(codec, WM8994_OUTPUT_MIXER_6);
+ val &= ~(WM8994_DACR_MIXOUTR_VOL_MASK);
+ val |= TUNING_RCV_OUTMIX6_VOL << WM8994_DACR_MIXOUTR_VOL_SHIFT;
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_6, val);
- val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME);
- val &= ~(WM8994_MIXOUTL_MUTE_N_MASK | WM8994_MIXOUTL_VOL_MASK);
- val |= (WM8994_MIXOUT_VU | WM8994_MIXOUTL_MUTE_N |
- TUNING_RCV_OPGAL_VOL);
- wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, val);
+ val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME);
+ val &= ~(WM8994_MIXOUTL_MUTE_N_MASK | WM8994_MIXOUTL_VOL_MASK);
+ val |= (WM8994_MIXOUT_VU | WM8994_MIXOUTL_MUTE_N |
+ TUNING_RCV_OPGAL_VOL);
+ wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, val);
- val = wm8994_read(codec, WM8994_RIGHT_OPGA_VOLUME);
- val &= ~(WM8994_MIXOUTR_MUTE_N_MASK | WM8994_MIXOUTR_VOL_MASK);
- val |= (WM8994_MIXOUT_VU | WM8994_MIXOUTR_MUTE_N |
- TUNING_RCV_OPGAR_VOL);
- wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val);
+ val = wm8994_read(codec, WM8994_RIGHT_OPGA_VOLUME);
+ val &= ~(WM8994_MIXOUTR_MUTE_N_MASK | WM8994_MIXOUTR_VOL_MASK);
+ val |= (WM8994_MIXOUT_VU | WM8994_MIXOUTR_MUTE_N |
+ TUNING_RCV_OPGAR_VOL);
+ wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val);
- val = wm8994_read(codec, WM8994_HPOUT2_VOLUME);
- val &= ~(WM8994_HPOUT2_MUTE_MASK | WM8994_HPOUT2_VOL_MASK);
- val |= TUNING_HPOUT2_VOL << WM8994_HPOUT2_VOL_SHIFT;
- wm8994_write(codec, WM8994_HPOUT2_VOLUME, val);
+ val = wm8994_read(codec, WM8994_HPOUT2_VOLUME);
+ val &= ~(WM8994_HPOUT2_MUTE_MASK | WM8994_HPOUT2_VOL_MASK);
+ val |= TUNING_HPOUT2_VOL << WM8994_HPOUT2_VOL_SHIFT;
+ wm8994_write(codec, WM8994_HPOUT2_VOLUME, val);
- /* Unmute DAC1 left */
- val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
- val &= ~(WM8994_DAC1L_MUTE_MASK | WM8994_DAC1L_VOL_MASK);
- val |= TUNING_DAC1L_VOL;
- wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val);
+ /* Unmute DAC1 left */
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
+ val &= ~(WM8994_DAC1L_MUTE_MASK | WM8994_DAC1L_VOL_MASK);
+ val |= TUNING_DAC1L_VOL;
+ 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_DAC1R_VOL_MASK);
- val |= TUNING_DAC1R_VOL;
- wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val);
- }
+ /* Unmute and volume ctrl RightDAC */
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME);
+ val &= ~(WM8994_DAC1R_MUTE_MASK | WM8994_DAC1R_VOL_MASK);
+ val |= TUNING_DAC1R_VOL;
+ wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_AIF1_DAC1_LEFT_VOLUME);
+ val &= ~(WM8994_AIF1DAC1L_VOL_MASK);
+ val |= (WM8994_AIF1DAC1_VU | TUNING_DAC1L_VOL);
+ wm8994_write(codec, WM8994_AIF1_DAC1_LEFT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME);
+ val &= ~(WM8994_AIF1DAC1R_VOL_MASK);
+ val |= (WM8994_AIF1DAC1_VU | TUNING_DAC1R_VOL);
+ wm8994_write(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME, val);
val = wm8994_read(codec, WM8994_OUTPUT_MIXER_1);
val &= ~(WM8994_DAC1L_TO_MIXOUTL_MASK);
@@ -997,63 +852,15 @@ void wm8994_set_playback_headset(struct snd_soc_codec *codec)
u16 val;
- u16 TestReturn1 = 0;
- u16 TestReturn2 = 0;
- u16 TestLow1 = 0;
- u16 TestHigh1 = 0;
- u8 TestLow = 0;
- u8 TestHigh = 0;
+ u16 testreturn1 = 0;
+ u16 testreturn2 = 0;
+ u16 testlow1 = 0;
+ u16 testhigh1 = 0;
+ u8 testlow = 0;
+ u8 testhigh = 0;
DEBUG_LOG("");
- val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1);
- val &= ~(WM8994_BIAS_ENA_MASK | WM8994_VMID_SEL_NORMAL);
- val |= (WM8994_BIAS_ENA | WM8994_VMID_SEL_NORMAL);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, 0x0003);
-
- if (!wm8994->testmode_config_flag) {
- val = wm8994_read(codec, WM8994_OUTPUT_MIXER_5);
- val &= ~(WM8994_DACL_MIXOUTL_VOL_MASK);
- val |= TUNING_EAR_OUTMIX5_VOL << WM8994_DACL_MIXOUTL_VOL_SHIFT;
- wm8994_write(codec, WM8994_OUTPUT_MIXER_5, val);
-
- val = wm8994_read(codec, WM8994_OUTPUT_MIXER_6);
- val &= ~(WM8994_DACR_MIXOUTR_VOL_MASK);
- val |= TUNING_EAR_OUTMIX6_VOL << WM8994_DACR_MIXOUTR_VOL_SHIFT;
- wm8994_write(codec, WM8994_OUTPUT_MIXER_6, val);
-
- val = wm8994_read(codec, WM8994_LEFT_OUTPUT_VOLUME);
- val &= ~(WM8994_HPOUT1L_MUTE_N_MASK | WM8994_HPOUT1L_VOL_MASK);
- val |= (WM8994_HPOUT1_VU | WM8994_HPOUT1L_MUTE_N |
- TUNING_MP3_OUTPUTL_VOL);
- wm8994_write(codec, WM8994_LEFT_OUTPUT_VOLUME, val);
-
- val = wm8994_read(codec, WM8994_RIGHT_OUTPUT_VOLUME);
- val &= ~(WM8994_HPOUT1R_MUTE_N_MASK | WM8994_HPOUT1R_VOL_MASK);
- val |= (WM8994_HPOUT1_VU | WM8994_HPOUT1R_MUTE_N |
- TUNING_MP3_OUTPUTR_VOL);
- wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, val);
-
- val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME);
- val &= ~(WM8994_MIXOUTL_MUTE_N_MASK | WM8994_MIXOUTL_VOL_MASK);
- val |= (WM8994_MIXOUT_VU | WM8994_MIXOUTL_MUTE_N |
- TUNING_MP3_OPGAL_VOL);
- wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, val);
-
- val = wm8994_read(codec, WM8994_RIGHT_OPGA_VOLUME);
- val &= ~(WM8994_MIXOUTR_MUTE_N_MASK | WM8994_MIXOUTR_VOL_MASK);
- val |= (WM8994_MIXOUT_VU | WM8994_MIXOUTR_MUTE_N |
- TUNING_MP3_OPGAR_VOL);
- wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val);
- }
- /* Configuring the Digital Paths */
-
- /* Unmute the AF1DAC1 */
- val = wm8994_read(codec, WM8994_AIF1_DAC1_FILTERS_1);
- val &= ~(WM8994_AIF1DAC1_MUTE_MASK);
- val |= WM8994_AIF1DAC1_UNMUTE;
- wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, val);
-
/* Enable the Timeslot0 to DAC1L */
val = wm8994_read(codec, WM8994_DAC1_LEFT_MIXER_ROUTING);
val &= ~(WM8994_AIF1DAC1L_TO_DAC1L_MASK);
@@ -1066,18 +873,6 @@ void wm8994_set_playback_headset(struct snd_soc_codec *codec)
val |= WM8994_AIF1DAC1R_TO_DAC1R;
wm8994_write(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING, 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, 0x102);
val &= ~(0x0003);
val = 0x0003;
@@ -1093,16 +888,61 @@ void wm8994_set_playback_headset(struct snd_soc_codec *codec)
val = 0x0000;
wm8994_write(codec, 0x102, val);
- val = wm8994_read(codec, 0x5D);
- val &= ~(0x0002);
- val = 0x0002;
- wm8994_write(codec, 0x5D, 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 | WM8994_HPOUT1L_VOL_MASK);
+ if (wm8994->ringtone_active)
+ val |= (WM8994_HPOUT1_VU | WM8994_HPOUT1L_MUTE_N |
+ TUNING_RING_OUTPUTL_VOL);
+ else
+ val |= (WM8994_HPOUT1_VU | WM8994_HPOUT1L_MUTE_N |
+ TUNING_MP3_OUTPUTL_VOL);
+ wm8994_write(codec, WM8994_LEFT_OUTPUT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_RIGHT_OUTPUT_VOLUME);
+ val &= ~(WM8994_HPOUT1R_MUTE_N_MASK | WM8994_HPOUT1R_VOL_MASK);
+ if (wm8994->ringtone_active)
+ val |= (WM8994_HPOUT1_VU | WM8994_HPOUT1R_MUTE_N |
+ TUNING_RING_OUTPUTR_VOL);
+ else
+ val |= (WM8994_HPOUT1_VU | WM8994_HPOUT1R_MUTE_N |
+ TUNING_MP3_OUTPUTR_VOL);
+ wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME);
+ val &= ~(WM8994_MIXOUTL_MUTE_N_MASK | WM8994_MIXOUTL_VOL_MASK);
+ if (wm8994->ringtone_active)
+ val |= (WM8994_MIXOUT_VU | WM8994_MIXOUTL_MUTE_N |
+ TUNING_RING_OPGAL_VOL);
+ else
+ val |= (WM8994_MIXOUT_VU | WM8994_MIXOUTL_MUTE_N |
+ TUNING_MP3_OPGAL_VOL);
+ wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_RIGHT_OPGA_VOLUME);
+ val &= ~(WM8994_MIXOUTR_MUTE_N_MASK | WM8994_MIXOUTR_VOL_MASK);
+ if (wm8994->ringtone_active)
+ val |= (WM8994_MIXOUT_VU | WM8994_MIXOUTR_MUTE_N |
+ TUNING_RING_OPGAR_VOL);
+ else
+ val |= (WM8994_MIXOUT_VU | WM8994_MIXOUTR_MUTE_N |
+ TUNING_MP3_OPGAR_VOL);
+ wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_AIF1_DAC1_LEFT_VOLUME);
+ val &= ~(WM8994_AIF1DAC1L_VOL_MASK);
+ val |= (WM8994_AIF1DAC1_VU | TUNING_DAC1L_VOL);
+ wm8994_write(codec, WM8994_AIF1_DAC1_LEFT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME);
+ val &= ~(WM8994_AIF1DAC1R_VOL_MASK);
+ val |= (WM8994_AIF1DAC1_VU | TUNING_DAC1R_VOL);
+ wm8994_write(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME, val);
+
val = wm8994_read(codec, WM8994_DC_SERVO_2);
val &= ~(0x03E0);
val = 0x03E0;
@@ -1111,7 +951,8 @@ void wm8994_set_playback_headset(struct snd_soc_codec *codec)
/* 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_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);
@@ -1122,60 +963,76 @@ void wm8994_set_playback_headset(struct snd_soc_codec *codec)
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_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);
+
val = wm8994_read(codec, WM8994_DC_SERVO_1);
val &= ~(0x0303);
val = 0x0303;
wm8994_write(codec, WM8994_DC_SERVO_1, val);
- TestReturn1 = wm8994_read(codec, WM8994_DC_SERVO_4);
+ msleep(160);
+
+ testreturn1 = wm8994_read(codec, WM8994_DC_SERVO_4);
- TestLow = (u8) (TestReturn1 & 0xff);
- TestHigh = (u8) ((TestReturn1 >> 8) & 0xff);
+ testlow = (signed char)(testreturn1 & 0xff);
+ testhigh = (signed char)((testreturn1>>8) & 0xff);
- TestLow1 = ((u16) TestLow - 4) & 0x00ff;
- TestHigh1 = (((u16) TestHigh - 4 << 8) & 0xff00);
- TestReturn2 = TestLow1 | TestHigh1;
- wm8994_write(codec, WM8994_DC_SERVO_4, TestReturn2);
+ testlow1 = ((signed short)(testlow-5)) & 0x00ff;
+ testhigh1 = (((signed short)(testhigh-5)<<8) & 0xff00);
+ testreturn2 = testlow1|testhigh1;
+ wm8994_write(codec, WM8994_DC_SERVO_4, testreturn2);
val = wm8994_read(codec, WM8994_DC_SERVO_1);
val &= ~(0x000F);
val = 0x000F;
wm8994_write(codec, WM8994_DC_SERVO_1, val);
- /* msleep(20);*/ /* commenting sleep as not required in SLSI platform */
- DEBUG_LOG("Sleep 15ms");
+ msleep(20);
/* 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 |
+ 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);
- /* 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 MIXOUT */
- 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_MIXOUTLVOL_ENA | WM8994_MIXOUTRVOL_ENA |
- WM8994_MIXOUTL_ENA | WM8994_MIXOUTR_ENA);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, 0x0030);
-
/* Unmute DAC1 left */
val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
val &= ~(WM8994_DAC1L_MUTE_MASK | WM8994_DAC1L_VOL_MASK);
@@ -1188,6 +1045,12 @@ void wm8994_set_playback_headset(struct snd_soc_codec *codec)
val |= TUNING_DAC1R_VOL;
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)
@@ -1204,49 +1067,68 @@ void wm8994_set_playback_speaker(struct snd_soc_codec *codec)
wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val);
val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_3);
- val &= ~(WM8994_SPKLVOL_ENA_MASK);
+ 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 */
- if (!wm8994->testmode_config_flag) {
- /* Unmute the SPKMIXVOLUME */
- val = wm8994_read(codec, WM8994_SPKMIXL_ATTENUATION);
- val &= ~(WM8994_SPKMIXL_VOL_MASK);
- val |= TUNING_SPKMIXL_ATTEN;
- wm8994_write(codec, WM8994_SPKMIXL_ATTENUATION, val);
-
- val = wm8994_read(codec, WM8994_SPKMIXR_ATTENUATION);
- val &= ~(WM8994_SPKMIXR_VOL_MASK);
- wm8994_write(codec, WM8994_SPKMIXR_ATTENUATION, val);
-
- val = wm8994_read(codec, WM8994_SPEAKER_VOLUME_LEFT);
- val &= ~(WM8994_SPKOUTL_MUTE_N_MASK | WM8994_SPKOUTL_VOL_MASK);
+ /* Unmute the SPKMIXVOLUME */
+ val = wm8994_read(codec, WM8994_SPKMIXL_ATTENUATION);
+ val &= ~(WM8994_SPKMIXL_VOL_MASK);
+ val |= TUNING_SPKMIXL_ATTEN;
+ wm8994_write(codec, WM8994_SPKMIXL_ATTENUATION, val);
+
+ val = wm8994_read(codec, WM8994_SPKMIXR_ATTENUATION);
+ val &= ~(WM8994_SPKMIXR_VOL_MASK);
+ wm8994_write(codec, WM8994_SPKMIXR_ATTENUATION, val);
+
+ val = wm8994_read(codec, WM8994_SPEAKER_VOLUME_LEFT);
+ val &= ~(WM8994_SPKOUTL_MUTE_N_MASK | WM8994_SPKOUTL_VOL_MASK);
+ if (wm8994->ringtone_active)
+ val |= (WM8994_SPKOUT_VU | WM8994_SPKOUTL_MUTE_N |
+ TUNING_RING_SPKL_VOL);
+ else
val |= (WM8994_SPKOUT_VU | WM8994_SPKOUTL_MUTE_N |
- TUNING_MP3_SPKL_VOL);
- wm8994_write(codec, WM8994_SPEAKER_VOLUME_LEFT, val);
+ TUNING_MP3_SPKL_VOL);
+ 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_CLASSD);
+ val &= ~(WM8994_SPKOUTL_BOOST_MASK);
+ if (wm8994->ringtone_active)
+ val |= TUNING_RING_CLASSD_VOL <<
+ WM8994_SPKOUTL_BOOST_SHIFT;
+ else
+ val |= TUNING_MP3_CLASSD_VOL <<
+ WM8994_SPKOUTL_BOOST_SHIFT;
+ wm8994_write(codec, WM8994_CLASSD, 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);
+ /* Unmute DAC1 left */
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
+ val &= ~(WM8994_DAC1L_MUTE_MASK | WM8994_DAC1L_VOL_MASK);
+ val |= TUNING_DAC1L_VOL;
+ wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val);
- val = wm8994_read(codec, WM8994_CLASSD);
- val &= ~(WM8994_SPKOUTL_BOOST_MASK);
- val |= TUNING_MP3_CLASSD_VOL << WM8994_SPKOUTL_BOOST_SHIFT;
- wm8994_write(codec, WM8994_CLASSD, val);
+ /* Unmute and volume ctrl RightDAC */
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME);
+ val &= ~(WM8994_DAC1R_MUTE_MASK | WM8994_DAC1R_VOL_MASK);
+ val |= TUNING_DAC1R_VOL;
+ wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val);
- /* Unmute DAC1 left */
- val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
- val &= ~(WM8994_DAC1L_MUTE_MASK | WM8994_DAC1L_VOL_MASK);
- val |= TUNING_DAC1L_VOL;
- wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val);
+ val = wm8994_read(codec, WM8994_AIF1_DAC1_LEFT_VOLUME);
+ val &= ~(WM8994_AIF1DAC1L_VOL_MASK);
+ val |= (WM8994_AIF1DAC1_VU | TUNING_DAC1L_VOL);
+ wm8994_write(codec, WM8994_AIF1_DAC1_LEFT_VOLUME, val);
- /* Unmute and volume ctrl RightDAC */
- val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME);
- val &= ~(WM8994_DAC1R_MUTE_MASK | WM8994_DAC1R_VOL_MASK);
- val |= TUNING_DAC1R_VOL;
- wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val);
- }
+ val = wm8994_read(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME);
+ val &= ~(WM8994_AIF1DAC1R_VOL_MASK);
+ val |= (WM8994_AIF1DAC1_VU | TUNING_DAC1R_VOL);
+ wm8994_write(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME, val);
val = wm8994_read(codec, WM8994_SPKOUT_MIXERS);
val &= ~(WM8994_SPKMIXL_TO_SPKOUTL_MASK |
@@ -1263,14 +1145,15 @@ void wm8994_set_playback_speaker(struct snd_soc_codec *codec)
/* Eable DAC1 Left and timeslot left */
val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_5);
- val &= ~(WM8994_DAC1L_ENA_MASK | WM8994_AIF1DAC1L_ENA_MASK);
- val |= (WM8994_AIF1DAC1L_ENA | WM8994_DAC1L_ENA);
+ 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);
/* Unmute */
val = wm8994_read(codec, WM8994_AIF1_DAC1_FILTERS_1);
- val &= ~(WM8994_AIF1DAC1_MUTE_MASK);
- val |= WM8994_AIF1DAC1_UNMUTE;
+ 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);
/* enable timeslot0 to left dac */
@@ -1282,9 +1165,11 @@ void wm8994_set_playback_speaker(struct snd_soc_codec *codec)
/* Enbale bias,vmid and Left speaker */
val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1);
val &= ~(WM8994_BIAS_ENA_MASK | WM8994_VMID_SEL_MASK |
- WM8994_SPKOUTL_ENA_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);
+
}
void wm8994_set_playback_speaker_headset(struct snd_soc_codec *codec)
@@ -1292,23 +1177,13 @@ void wm8994_set_playback_speaker_headset(struct snd_soc_codec *codec)
struct wm8994_priv *wm8994 = codec->drvdata;
u16 val;
- int ret;
-
- u16 nReadServo4Val = NULL;
- u16 ncompensationResult = NULL;
- u16 nServo4Low = NULL;
- u16 nServo4High = NULL;
- u8 nCompensationResultLow = 0;
- u8 nCompensationResultHigh = 0;
-
- DEBUG_LOG("testmode_config_flag = [%d]", wm8994->testmode_config_flag);
- /* ------------------ Common Settings ------------------ */
- /* Unmute the AIF1DAC1 */
- val = wm8994_read(codec, WM8994_AIF1_DAC1_FILTERS_1);
- val &= ~(WM8994_AIF1DAC1_MUTE_MASK);
- val |= WM8994_AIF1DAC1_UNMUTE;
- wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, val);
+ u16 nreadservo4val = 0;
+ u16 ncompensationresult = 0;
+ u16 ncompensationresultlow = 0;
+ u16 ncompensationresulthigh = 0;
+ u8 nservo4low = 0;
+ u8 nservo4high = 0;
/* Enable the Timeslot0 to DAC1L */
val = wm8994_read(codec, WM8994_DAC1_LEFT_MIXER_ROUTING);
@@ -1316,57 +1191,51 @@ void wm8994_set_playback_speaker_headset(struct snd_soc_codec *codec)
val |= WM8994_AIF1DAC1L_TO_DAC1L;
wm8994_write(codec, WM8994_DAC1_LEFT_MIXER_ROUTING, val);
- /* Disable end point for preventing pop up noise. */
- val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1);
- val &= ~(WM8994_HPOUT1L_ENA_MASK | WM8994_HPOUT1R_ENA_MASK |
- WM8994_SPKOUTL_ENA_MASK);
- ret = wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, 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 Path Settings ------------------ */
+ val = wm8994_read(codec, WM8994_AIF1_DAC1_LEFT_VOLUME);
+ val &= ~(WM8994_AIF1DAC1L_VOL_MASK);
+ val |= (WM8994_AIF1DAC1_VU | TUNING_DAC1L_VOL);
+ wm8994_write(codec, WM8994_AIF1_DAC1_LEFT_VOLUME, val);
- /* Speaker Volume Control */
- if (!wm8994->testmode_config_flag) {
- /* Unmute the SPKMIXVOLUME */
- val = wm8994_read(codec, WM8994_SPKMIXL_ATTENUATION);
- val &= ~(WM8994_SPKMIXL_VOL_MASK);
- val |= TUNING_SPKMIXL_ATTEN;
- wm8994_write(codec, WM8994_SPKMIXL_ATTENUATION, val);
-
- val = wm8994_read(codec, WM8994_SPKMIXR_ATTENUATION);
- val &= ~(WM8994_SPKMIXR_VOL_MASK);
- wm8994_write(codec, WM8994_SPKMIXR_ATTENUATION, val);
-
- val = wm8994_read(codec, WM8994_SPEAKER_VOLUME_LEFT);
- val &= ~(WM8994_SPKOUTL_MUTE_N_MASK | WM8994_SPKOUTL_VOL_MASK);
- val |= (WM8994_SPKOUTL_MUTE_N | TUNING_MP3_SPKL_VOL);
- 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_CLASSD);
- val &= ~(WM8994_SPKOUTL_BOOST_MASK);
- val |= TUNING_MP3_CLASSD_VOL << WM8994_SPKOUTL_BOOST_SHIFT;
- wm8994_write(codec, WM8994_CLASSD, val);
-
- /* Unmute DAC1 left */
- val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
- val &= ~(WM8994_DAC1L_MUTE_MASK | WM8994_DAC1L_VOL_MASK);
- val |= TUNING_DAC1L_VOL;
- wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val);
+ val = wm8994_read(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME);
+ val &= ~(WM8994_AIF1DAC1R_VOL_MASK);
+ val |= (WM8994_AIF1DAC1_VU | TUNING_DAC1R_VOL);
+ wm8994_write(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME, val);
- /* Unmute and volume ctrl RightDAC */
- val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME);
- val &= ~(WM8994_DAC1R_MUTE_MASK | WM8994_DAC1R_VOL_MASK);
- val |= TUNING_DAC1R_VOL;
- wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val);
- }
+ /* Speaker Volume Control */
+ val = wm8994_read(codec, WM8994_SPEAKER_VOLUME_LEFT);
+ val &= ~(WM8994_SPKOUTL_MUTE_N_MASK | WM8994_SPKOUTL_VOL_MASK);
+ if (wm8994->ringtone_active)
+ val |= (WM8994_SPKOUT_VU | WM8994_SPKOUTL_MUTE_N |
+ TUNING_RING_SPKL_VOL);
+ else
+ val |= (WM8994_SPKOUT_VU | WM8994_SPKOUTL_MUTE_N |
+ TUNING_MP3_SPKL_VOL);
+ 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_CLASSD);
+ val &= ~(WM8994_SPKOUTL_BOOST_MASK);
+ if (wm8994->ringtone_active)
+ val |= TUNING_RING_CLASSD_VOL <<
+ WM8994_SPKOUTL_BOOST_SHIFT;
+ else
+ val |= TUNING_MP3_CLASSD_VOL <<
+ WM8994_SPKOUTL_BOOST_SHIFT;
+ wm8994_write(codec, WM8994_CLASSD, val);
val = wm8994_read(codec, WM8994_SPKOUT_MIXERS);
val &= ~(WM8994_SPKMIXL_TO_SPKOUTL_MASK |
- WM8994_SPKMIXR_TO_SPKOUTL_MASK |
- WM8994_SPKMIXR_TO_SPKOUTR_MASK);
+ WM8994_SPKMIXR_TO_SPKOUTL_MASK |
+ WM8994_SPKMIXR_TO_SPKOUTR_MASK);
val |= WM8994_SPKMIXL_TO_SPKOUTL;
wm8994_write(codec, WM8994_SPKOUT_MIXERS, val);
@@ -1376,28 +1245,7 @@ void wm8994_set_playback_speaker_headset(struct snd_soc_codec *codec)
val |= WM8994_DAC1L_TO_SPKMIXL;
wm8994_write(codec, WM8994_SPEAKER_MIXER, val);
- /* ------------------ Ear Path Settings ------------------ */
-
- /* 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);
-
/* Configuring the Digital Paths */
-
- /* 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;
@@ -1413,16 +1261,31 @@ void wm8994_set_playback_speaker_headset(struct snd_soc_codec *codec)
val = 0x0000;
wm8994_write(codec, 0x102, val);
- val = wm8994_read(codec, 0x5D);
- val &= ~(0x0002);
- val = 0x0002;
- wm8994_write(codec, 0x5D, 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 | WM8994_HPOUT1L_VOL_MASK);
+ if (wm8994->ringtone_active)
+ val |= (WM8994_HPOUT1_VU | WM8994_HPOUT1L_MUTE_N |
+ TUNING_RING_DUAL_OUTPUTL_VOL);
+ else
+ val |= (WM8994_HPOUT1_VU | WM8994_HPOUT1L_MUTE_N |
+ TUNING_MP3_DUAL_OUTPUTL_VOL);
+ wm8994_write(codec, WM8994_LEFT_OUTPUT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_RIGHT_OUTPUT_VOLUME);
+ val &= ~(WM8994_HPOUT1R_MUTE_N_MASK | WM8994_HPOUT1R_VOL_MASK);
+ if (wm8994->ringtone_active)
+ val |= (WM8994_HPOUT1_VU | WM8994_HPOUT1R_MUTE_N |
+ TUNING_RING_DUAL_OUTPUTR_VOL);
+ else
+ val |= (WM8994_HPOUT1_VU | WM8994_HPOUT1L_MUTE_N |
+ TUNING_MP3_DUAL_OUTPUTR_VOL);
+ wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, val);
+
/* DC Servo Series Count */
val = 0x03E0;
wm8994_write(codec, WM8994_DC_SERVO_2, val);
@@ -1431,20 +1294,50 @@ void wm8994_set_playback_speaker_headset(struct snd_soc_codec *codec)
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);
+ 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_MASK ;
val |= WM8994_CP_ENA | WM8994_CP_ENA_DEFAULT;
wm8994_write(codec, WM8994_CHARGE_PUMP_1, val);
- msleep(20);
+ 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 */
val = (WM8994_DCS_TRIG_SERIES_1 | WM8994_DCS_TRIG_SERIES_0 |
@@ -1453,109 +1346,204 @@ void wm8994_set_playback_speaker_headset(struct snd_soc_codec *codec)
msleep(160);
- nReadServo4Val = wm8994_read(codec, WM8994_DC_SERVO_4);
- nServo4Low = (u8) (nReadServo4Val & 0xff);
- nServo4High = (u8) ((nReadServo4Val >> 8) & 0xff);
+ nreadservo4val = wm8994_read(codec, WM8994_DC_SERVO_4);
+ nservo4low = (signed char)(nreadservo4val & 0xff);
+ nservo4high = (signed char)((nreadservo4val>>8) & 0xff);
- nCompensationResultLow = ((u16) nServo4Low - 4) & 0x00ff;
- nCompensationResultHigh = (((u16) nServo4High - 4) << 8) & 0xff00;
- ncompensationResult = nCompensationResultLow | nCompensationResultHigh;
- wm8994_write(codec, WM8994_DC_SERVO_4, ncompensationResult);
+ ncompensationresultlow = ((signed short)nservo4low - 5) & 0x00ff;
+ ncompensationresulthigh = ((signed short)(nservo4high - 5)<<8) & 0xff00;
+ ncompensationresult = ncompensationresultlow|ncompensationresulthigh;
+ wm8994_write(codec, WM8994_DC_SERVO_4, ncompensationresult);
val = (WM8994_DCS_TRIG_DAC_WR_1 | WM8994_DCS_TRIG_DAC_WR_0 |
WM8994_DCS_ENA_CHAN_1 | WM8994_DCS_ENA_CHAN_0);
wm8994_write(codec, WM8994_DC_SERVO_1, val);
- msleep(20);
+ msleep(15);
- /* 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_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);
- /* Enable DAC1 and DAC2 and the Timeslot0 for AIF1 */
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
+ val &= ~(WM8994_DAC1L_MUTE_MASK | WM8994_DAC1L_VOL_MASK);
+ val |= TUNING_DAC1L_VOL;
+ wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME);
+ val &= ~(WM8994_DAC1R_MUTE_MASK | WM8994_DAC1R_VOL_MASK);
+ val |= TUNING_DAC1R_VOL;
+ 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);
+
+ val = wm8994_read(codec, WM8994_SPKMIXL_ATTENUATION);
+ val &= ~(WM8994_SPKMIXL_VOL_MASK);
+ val |= TUNING_SPKMIXL_ATTEN;
+ wm8994_write(codec, WM8994_SPKMIXL_ATTENUATION, val);
+
+ val = wm8994_read(codec, WM8994_SPKMIXR_ATTENUATION);
+ val &= ~(WM8994_SPKMIXR_VOL_MASK);
+ wm8994_write(codec, WM8994_SPKMIXR_ATTENUATION, val);
+
+}
+
+void wm8994_set_playback_bluetooth(struct snd_soc_codec *codec)
+{
+ u16 val;
+
+ DEBUG_LOG("BT Playback Path for Voice Command\n");
+
+ wm8994_set_voicecall_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_DAC1R_ENA_MASK | WM8994_DAC1L_ENA_MASK |
- WM8994_AIF1DAC1R_ENA_MASK | WM8994_AIF1DAC1L_ENA_MASK);
- val |= (WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA |
+ 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);
- /* 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_MIXOUTLVOL_ENA | WM8994_MIXOUTRVOL_ENA |
- WM8994_MIXOUTL_ENA | WM8994_MIXOUTR_ENA |
- WM8994_SPKLVOL_ENA);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, 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);
- if (!wm8994->testmode_config_flag) {
- val = wm8994_read(codec, WM8994_OUTPUT_MIXER_5);
- val &= ~(WM8994_DACL_MIXOUTL_VOL_MASK);
- val |= TUNING_EAR_OUTMIX5_VOL << WM8994_DACL_MIXOUTL_VOL_SHIFT;
- wm8994_write(codec, WM8994_OUTPUT_MIXER_5, val);
+ /* 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);
- val = wm8994_read(codec, WM8994_OUTPUT_MIXER_6);
- val &= ~(WM8994_DACR_MIXOUTR_VOL_MASK);
- val |= TUNING_EAR_OUTMIX6_VOL << WM8994_DACR_MIXOUTR_VOL_SHIFT;
- wm8994_write(codec, WM8994_OUTPUT_MIXER_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_LEFT_OUTPUT_VOLUME);
- val &= ~(WM8994_HPOUT1L_MUTE_N_MASK | WM8994_HPOUT1L_VOL_MASK);
- val |= (WM8994_HPOUT1_VU | WM8994_HPOUT1L_MUTE_N |
- TUNING_DUAL_OUTPUTL_VOL);
- wm8994_write(codec, WM8994_LEFT_OUTPUT_VOLUME, 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);
- val = wm8994_read(codec, WM8994_RIGHT_OUTPUT_VOLUME);
- val &= ~(WM8994_HPOUT1R_MUTE_N_MASK | WM8994_HPOUT1R_VOL_MASK);
- val |= (WM8994_HPOUT1_VU | WM8994_HPOUT1R_MUTE_N |
- TUNING_DUAL_OUTPUTR_VOL);
- wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, 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);
}
void wm8994_set_voicecall_common_setting(struct snd_soc_codec *codec)
{
- /*GPIO Configuration */
+ int val;
+
+ /* 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_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);
- /*FLL2 Setting */
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_AIF2_CLOCKING_1, 0x0019);
wm8994_write(codec, WM8994_FLL2_CONTROL_1,
- WM8994_FLL2_FRACN_ENA | WM8994_FLL2_ENA);
-
- /*Clocking */
- wm8994_write(codec, WM8994_CLOCKING_1, WM8994_DSP_FS2CLK_ENA |
- WM8994_DSP_FSINTCLK_ENA | WM8994_SYSCLK_SRC);
- wm8994_write(codec, WM8994_CLOCKING_2, 0x1 << WM8994_TOCLK_DIV_SHIFT |
- 0x6 << WM8994_DBCLK_DIV_SHIFT |
- 0x3 << WM8994_OPCLK_DIV_SHIFT);
+ 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 */
+ /* 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 |
- WM8994_AIF2_LRCLK_INV | 0x1 << WM8994_AIF2_FMT_SHIFT);
+ 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_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);
+
+ val = wm8994_read(codec, WM8994_AIF1_DAC1_LEFT_VOLUME);
+ val &= ~(WM8994_AIF1DAC1L_VOL_MASK);
+ val |= (WM8994_AIF1DAC1_VU | TUNING_DAC1L_VOL);
+ wm8994_write(codec, WM8994_AIF1_DAC1_LEFT_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME);
+ val &= ~(WM8994_AIF1DAC1R_VOL_MASK);
+ val |= (WM8994_AIF1DAC1_VU | TUNING_DAC1R_VOL);
+ wm8994_write(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME, val);
+
+ wm8994_write(codec, 0x6, 0x0);
}
void wm8994_set_voicecall_receiver(struct snd_soc_codec *codec)
@@ -1566,26 +1554,22 @@ void wm8994_set_voicecall_receiver(struct snd_soc_codec *codec)
DEBUG_LOG("");
- audio_ctrl_mic_bias_gpio(1);
+ 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);
- /* Analogue Input Configuration -Main MIC */
wm8994_write(codec, WM8994_POWER_MANAGEMENT_2,
- WM8994_TSHUT_ENA | WM8994_TSHUT_OPDIS | WM8994_MIXINL_ENA |
- WM8994_IN1L_ENA);
+ 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_POWER_MANAGEMENT_5,
- WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA |
- WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA |
- WM8994_DAC1L_ENA | WM8994_DAC1R_ENA);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_6, 0x0000);
+ WM8994_AIF2ADCL_ENA | WM8994_ADCL_ENA);
wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, 0x0000);
wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, 0x0000);
@@ -1594,90 +1578,80 @@ void wm8994_set_voicecall_receiver(struct snd_soc_codec *codec)
wm8994_write(codec, WM8994_DAC2_LEFT_VOLUME, 0x01C0);
wm8994_write(codec, WM8994_DAC2_RIGHT_VOLUME, 0x01C0);
- /* AIF1 & AIF2 Output is connected to DAC1 */
- wm8994_write(codec, WM8994_DAC1_LEFT_MIXER_ROUTING,
- WM8994_AIF2DACL_TO_DAC1L | WM8994_AIF1DAC1L_TO_DAC1L);
- wm8994_write(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING,
- WM8994_AIF2DACR_TO_DAC1R | WM8994_AIF1DAC1R_TO_DAC1R);
-
/* Tx -> AIF2 Path */
wm8994_write(codec, WM8994_DAC2_LEFT_MIXER_ROUTING,
- WM8994_ADC1_TO_DAC2L);
+ WM8994_ADC1_TO_DAC2L);
wm8994_write(codec, WM8994_DAC2_RIGHT_MIXER_ROUTING,
- WM8994_ADC1_TO_DAC2R);
-
- if (!wm8994->testmode_config_flag) {
- /* Unmute 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 | TUNING_CALL_RCV_INPUTMIX_VOL);
- 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 |
- WM8994_IN1L_MIXINL_VOL_MASK |
- WM8994_MIXOUTL_MIXINL_VOL_MASK);
- val |= (WM8994_IN1L_TO_MIXINL | WM8994_IN1L_MIXINL_VOL);
- wm8994_write(codec, WM8994_INPUT_MIXER_3, val);
-
- /* Volume Control - Output */
- val = wm8994_read(codec, WM8994_OUTPUT_MIXER_5);
- val &= ~(WM8994_DACL_MIXOUTL_VOL_MASK);
- val |= TUNING_RCV_OUTMIX5_VOL << WM8994_DACL_MIXOUTL_VOL_SHIFT;
- wm8994_write(codec, WM8994_OUTPUT_MIXER_5, val);
+ WM8994_ADC1_TO_DAC2R);
- val = wm8994_read(codec, WM8994_OUTPUT_MIXER_6);
- val &= ~(WM8994_DACR_MIXOUTR_VOL_MASK);
- val |= TUNING_RCV_OUTMIX6_VOL << WM8994_DACR_MIXOUTR_VOL_SHIFT;
- wm8994_write(codec, WM8994_OUTPUT_MIXER_6, val);
+ wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019);
- val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME);
- val &= ~(WM8994_MIXOUTL_MUTE_N_MASK | WM8994_MIXOUTL_VOL_MASK);
- val |= (WM8994_MIXOUT_VU | WM8994_MIXOUTL_MUTE_N |
- TUNING_RCV_OPGAL_VOL);
- wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, val);
+ /* Unmute 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 | TUNING_CALL_RCV_INPUTMIX_VOL);
+ 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 |
+ WM8994_IN1L_MIXINL_VOL_MASK |
+ WM8994_MIXOUTL_MIXINL_VOL_MASK);
+ val |= (WM8994_IN1L_TO_MIXINL | TUNING_CALL_RCV_MIXER_VOL);
+ wm8994_write(codec, WM8994_INPUT_MIXER_3, val);
+
+ /* Volume Control - Output */
+ val = wm8994_read(codec, WM8994_OUTPUT_MIXER_5);
+ val &= ~(WM8994_DACL_MIXOUTL_VOL_MASK);
+ val |= TUNING_RCV_OUTMIX5_VOL << WM8994_DACL_MIXOUTL_VOL_SHIFT;
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_5, val);
+
+ val = wm8994_read(codec, WM8994_OUTPUT_MIXER_6);
+ val &= ~(WM8994_DACR_MIXOUTR_VOL_MASK);
+ val |= TUNING_RCV_OUTMIX6_VOL << WM8994_DACR_MIXOUTR_VOL_SHIFT;
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_6, val);
+
+ val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME);
+ val &= ~(WM8994_MIXOUTL_MUTE_N_MASK | WM8994_MIXOUTL_VOL_MASK);
+ val |= (WM8994_MIXOUT_VU | WM8994_MIXOUTL_MUTE_N |
+ TUNING_RCV_OPGAL_VOL);
+ wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_RIGHT_OPGA_VOLUME);
+ val &= ~(WM8994_MIXOUTR_MUTE_N_MASK | WM8994_MIXOUTR_VOL_MASK);
+ val |= (WM8994_MIXOUT_VU | WM8994_MIXOUTR_MUTE_N |
+ TUNING_RCV_OPGAR_VOL);
+ wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val);
+
+ val = wm8994_read(codec, WM8994_HPOUT2_VOLUME);
+ val &= ~(WM8994_HPOUT2_MUTE_MASK | WM8994_HPOUT2_VOL_MASK);
+ val |= TUNING_HPOUT2_VOL << WM8994_HPOUT2_VOL_SHIFT;
+ wm8994_write(codec, WM8994_HPOUT2_VOLUME, val);
- val = wm8994_read(codec, WM8994_RIGHT_OPGA_VOLUME);
- val &= ~(WM8994_MIXOUTR_MUTE_N_MASK | WM8994_MIXOUTR_VOL_MASK);
- val |= (WM8994_MIXOUT_VU | WM8994_MIXOUTR_MUTE_N |
- TUNING_RCV_OPGAR_VOL);
- wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val);
-
- val = wm8994_read(codec, WM8994_HPOUT2_VOLUME);
- val &= ~(WM8994_HPOUT2_MUTE_MASK | WM8994_HPOUT2_VOL_MASK);
- val |= TUNING_HPOUT2_VOL << WM8994_HPOUT2_VOL_SHIFT;
- wm8994_write(codec, WM8994_HPOUT2_VOLUME, val);
+ /* Unmute DAC1 left */
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
+ val &= ~(WM8994_DAC1L_MUTE_MASK | WM8994_DAC1L_VOL_MASK);
+ val |= TUNING_DAC1L_VOL;
+ wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val);
- /* Unmute DAC1 left */
- val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
- val &= ~(WM8994_DAC1L_MUTE_MASK | WM8994_DAC1L_VOL_MASK);
- val |= TUNING_DAC1L_VOL;
- 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_DAC1R_VOL_MASK);
+ val |= TUNING_DAC1R_VOL;
+ wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val);
- /* Unmute and volume ctrl RightDAC */
- val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME);
- val &= ~(WM8994_DAC1R_MUTE_MASK | WM8994_DAC1R_VOL_MASK);
- val |= TUNING_DAC1R_VOL; /* 0 db volume */
- 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);
- wm8994_set_voicecall_common_setting(codec);
-
/* 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_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_INPUT_MIXER_4, 0x0000 ); */
+ WM8994_HPOUT2_ENA | WM8994_VMID_SEL_NORMAL | WM8994_BIAS_ENA);
}
void wm8994_set_voicecall_headset(struct snd_soc_codec *codec)
@@ -1686,642 +1660,341 @@ void wm8994_set_voicecall_headset(struct snd_soc_codec *codec)
int val;
- DEBUG_LOG("");
-
- audio_ctrl_mic_bias_gpio(1);
+ u16 testreturn1 = 0;
+ u16 testreturn2 = 0;
+ u16 testlow1 = 0;
+ u16 testhigh1 = 0;
+ u8 testlow = 0;
+ u8 testhigh = 0;
- /*DCS*/ wm8994_write(codec, WM8994_DC_SERVO_4, 0x9C9C);
- wm8994_write(codec, WM8994_DC_SERVO_2, 0x054E);
- wm8994_write(codec, WM8994_DC_SERVO_1, 0x300f);
- wm8994_write(codec, WM8994_DC_SERVO_ANA_1, 0x0080);
- wm8994_write(codec, WM8994_DC_SERVO_ANA_2, 0x0080);
-
- /* Power - UP seqeunce- COLD Start Up */
- wm8994_write(codec, WM8994_ANTIPOP_2, 0x006C);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, 0x0003);
- wm8994_write(codec, WM8994_DC_SERVO_ANA_1, 0x00FF);
- wm8994_write(codec, WM8994_DC_SERVO_ANA_2, 0x00FF);
- wm8994_write(codec, WM8994_CHARGE_PUMP_1, 0x9F25);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, 0x0313);
- wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x0022);
- wm8994_write(codec, WM8994_DC_SERVO_1, 0x333F);
- wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x00EE);
-
- /*Analogue Input Configuration */
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, 0x6110);
- wm8994_write(codec, WM8994_INPUT_MIXER_2, 0x0003);
+ DEBUG_LOG("");
- /*Analogue Output Configuration */
- wm8994_write(codec, WM8994_OUTPUT_MIXER_1, 0x0100);
- wm8994_write(codec, WM8994_OUTPUT_MIXER_2, 0x0100);
- wm8994_write(codec, WM8994_CHARGE_PUMP_1, 0x9F25);
- wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x00EE);
+ audio_ctrl_mic_bias_gpio(wm8994->pdata, 1);
- /*Digital Path Enables and Unmutes */
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_4, 0x3003);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_5, 0x3303);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_6, 0x0000);
- wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, 0x0000);
- wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, 0x0000);
- wm8994_write(codec, WM8994_DAC1_LEFT_MIXER_ROUTING, 0x0005);
- wm8994_write(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING, 0x0005);
- wm8994_write(codec, WM8994_DAC2_LEFT_VOLUME, 0x01C0);
- wm8994_write(codec, WM8994_DAC2_RIGHT_VOLUME, 0x01C0);
+ 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_ADC1_TO_DAC2L);
- wm8994_write(codec, WM8994_DAC2_MIXER_VOLUMES, 0x018C);
+ WM8994_ADC2_TO_DAC2L);
+ wm8994_write(codec, WM8994_DAC2_MIXER_VOLUMES, 0x0180);
wm8994_write(codec, WM8994_SIDETONE, 0x01C0);
- } else { /* H/W Rev B */
+ } 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_ADC1_TO_DAC2L);
wm8994_write(codec, WM8994_SIDETONE, 0x01C1);
}
- /* Tx -> AIF2 Path */
- wm8994_write(codec, WM8994_DAC2_RIGHT_MIXER_ROUTING,
- WM8994_ADC1_TO_DAC2R);
-
- wm8994_set_voicecall_common_setting(codec);
-
- /* Unmute */
- if (!wm8994->testmode_config_flag) {
- val = wm8994_read(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME);
- val &= ~(WM8994_IN1R_MUTE_MASK | WM8994_IN1R_VOL_MASK);
- val |= (WM8994_IN1R_VU | TUNING_CALL_EAR_INPUTMIX_VOL);
- wm8994_write(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, val);
-
- /* unmute 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);
- val |= (WM8994_IN1R_TO_MIXINR); /* 0db */
- wm8994_write(codec, WM8994_INPUT_MIXER_4, val);
-
- /* Volume Control - Output */
- val = wm8994_read(codec, WM8994_OUTPUT_MIXER_5);
- val &= ~(WM8994_DACL_MIXOUTL_VOL_MASK);
- val |= TUNING_EAR_OUTMIX5_VOL << WM8994_DACL_MIXOUTL_VOL_SHIFT;
- wm8994_write(codec, WM8994_OUTPUT_MIXER_5, val);
-
- val = wm8994_read(codec, WM8994_OUTPUT_MIXER_6);
- val &= ~(WM8994_DACR_MIXOUTR_VOL_MASK);
- val |= TUNING_EAR_OUTMIX6_VOL << WM8994_DACR_MIXOUTR_VOL_SHIFT;
- wm8994_write(codec, WM8994_OUTPUT_MIXER_6, val);
-
- val = wm8994_read(codec, WM8994_LEFT_OUTPUT_VOLUME);
- val &= ~(WM8994_HPOUT1L_MUTE_N_MASK | WM8994_HPOUT1L_VOL_MASK);
- val |= (WM8994_HPOUT1_VU | WM8994_HPOUT1L_MUTE_N |
- TUNING_CALL_OUTPUTL_VOL);
- wm8994_write(codec, WM8994_LEFT_OUTPUT_VOLUME, val);
-
- val = wm8994_read(codec, WM8994_RIGHT_OUTPUT_VOLUME);
- val &= ~(WM8994_HPOUT1R_MUTE_N_MASK | WM8994_HPOUT1R_VOL_MASK);
- val |= (WM8994_HPOUT1_VU | WM8994_HPOUT1R_MUTE_N |
- TUNING_CALL_OUTPUTR_VOL);
- wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, val);
-
- val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME);
- val &= ~(WM8994_MIXOUTL_MUTE_N_MASK | WM8994_MIXOUTL_VOL_MASK);
- val |= (WM8994_MIXOUT_VU | WM8994_MIXOUTL_MUTE_N |
- TUNING_CALL_OPGAL_VOL);
- wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, val);
-
- val = wm8994_read(codec, WM8994_RIGHT_OPGA_VOLUME);
- val &= ~(WM8994_MIXOUTR_MUTE_N_MASK | WM8994_MIXOUTR_VOL_MASK);
- val |= (WM8994_MIXOUT_VU | WM8994_MIXOUTR_MUTE_N |
- TUNING_CALL_OPGAR_VOL);
- wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val);
-
- /* Unmute DAC1 left */
- val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
- val &= ~(WM8994_DAC1L_MUTE_MASK | WM8994_DAC1L_VOL_MASK);
- val |= TUNING_DAC1L_VOL;
- 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_DAC1R_VOL_MASK);
- val |= TUNING_DAC1R_VOL;
- wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val);
- }
-
- /*DCS*/
- wm8994_write(codec, WM8994_DC_SERVO_4, 0x9C9C);
- wm8994_write(codec, WM8994_DC_SERVO_2, 0x054E);
- wm8994_write(codec, WM8994_DC_SERVO_1, 0x300f);
- wm8994_write(codec, WM8994_DC_SERVO_ANA_1, 0x0080);
- wm8994_write(codec, WM8994_DC_SERVO_ANA_2, 0x0080);
-}
-
-void wm8994_set_voicecall_speaker(struct snd_soc_codec *codec)
-{
- struct wm8994_priv *wm8994 = codec->drvdata;
-
- int val;
-
- DEBUG_LOG("");
-
- audio_ctrl_mic_bias_gpio(1);
-
- wm8994_write(codec, 0x39, 0x006C);
- /*Analogue Configuration */
- wm8994_write(codec, 0x01, 0x0003);
- /*Analogue Input Configuration */
- wm8994_write(codec, 0x02, 0x6240);
+ /* 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);
- /*Analogue Output Configuration */
- wm8994_write(codec, 0x03, 0x0300);
+ val = wm8994_read(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME);
+ val &= ~(WM8994_IN1R_MUTE_MASK | WM8994_IN1R_VOL_MASK);
+ val |= (WM8994_IN1R_VU | TUNING_CALL_EAR_INPUTMIX_VOL);
+ wm8994_write(codec, WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, val);
- wm8994_write(codec, WM8994_INPUT_MIXER_2,
- WM8994_IN1LP_TO_IN1L | WM8994_IN1LN_TO_IN1L);
+ val = wm8994_read(codec, WM8994_INPUT_MIXER_4);
+ val &= ~(WM8994_IN1R_TO_MIXINR_MASK |
+ WM8994_IN1R_MIXINR_VOL_MASK |
+ WM8994_MIXOUTR_MIXINR_VOL_MASK);
+ val |= (WM8994_IN1R_TO_MIXINR);
+ wm8994_write(codec, WM8994_INPUT_MIXER_4, val);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_4,
- WM8994_AIF2ADCL_ENA | WM8994_ADCL_ENA);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_5,
- WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA |
- WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA |
- WM8994_DAC1L_ENA | WM8994_DAC1R_ENA);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_6, 0x0000);
-
- if (!wm8994->testmode_config_flag) {
- /* Volume Control - Input */
- val = wm8994_read(codec, WM8994_INPUT_MIXER_3);
- val &= ~(WM8994_IN1L_TO_MIXINL_MASK |
- WM8994_IN1L_MIXINL_VOL_MASK |
- WM8994_MIXOUTL_MIXINL_VOL_MASK);
- val |= (WM8994_IN1L_TO_MIXINL);
- wm8994_write(codec, WM8994_INPUT_MIXER_3, 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);
- val = wm8994_read(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME);
- val &= ~(WM8994_IN1L_MUTE_MASK | WM8994_IN1L_VOL_MASK);
- val |= (WM8994_IN1L_VU | TUNING_CALL_SPK_INPUTMIX_VOL);
- wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME, val);
-
- /* Volume Control - Output */
- /* Unmute the SPKMIXVOLUME */
- val = wm8994_read(codec, WM8994_SPKMIXL_ATTENUATION);
- val &= ~(WM8994_SPKMIXL_VOL_MASK);
- val |= TUNING_SPKMIXL_ATTEN;
- wm8994_write(codec, WM8994_SPKMIXL_ATTENUATION, val);
-
- val = wm8994_read(codec, WM8994_SPKMIXR_ATTENUATION);
- val &= ~(WM8994_SPKMIXR_VOL_MASK);
- val |= TUNING_SPKMIXR_ATTEN;
- wm8994_write(codec, WM8994_SPKMIXR_ATTENUATION, val);
-
- val = wm8994_read(codec, WM8994_SPEAKER_VOLUME_LEFT);
- val &= ~(WM8994_SPKOUTL_MUTE_N_MASK | WM8994_SPKOUTL_VOL_MASK);
- val |= (WM8994_SPKOUT_VU | WM8994_SPKOUTL_MUTE_N |
- TUNING_CALL_SPKL_VOL);
- wm8994_write(codec, WM8994_SPEAKER_VOLUME_LEFT, val);
+ /* Unmute*/
+ val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME);
+ val &= ~(WM8994_MIXOUTL_MUTE_N_MASK | WM8994_MIXOUTL_VOL_MASK);
+ val |= (WM8994_MIXOUT_VU | WM8994_MIXOUTL_MUTE_N |
+ TUNING_CALL_OPGAL_VOL);
+ wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, 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_RIGHT_OPGA_VOLUME);
+ val &= ~(WM8994_MIXOUTR_MUTE_N_MASK | WM8994_MIXOUTR_VOL_MASK);
+ val |= (WM8994_MIXOUT_VU | WM8994_MIXOUTR_MUTE_N |
+ TUNING_CALL_OPGAR_VOL);
+ wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val);
- val = wm8994_read(codec, WM8994_CLASSD);
- val &= ~(WM8994_SPKOUTL_BOOST_MASK);
- val |= TUNING_CALL_CLASSD_VOL << WM8994_SPKOUTL_BOOST_SHIFT;
- wm8994_write(codec, WM8994_CLASSD, val);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_4, 0x2001);
- /* Unmute DAC1 left */
- val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
- val &= ~(WM8994_DAC1L_MUTE_MASK | WM8994_DAC1L_VOL_MASK);
- val |= TUNING_DAC1L_VOL;
- wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val);
+ val = wm8994_read(codec, 0x102);
+ val &= ~(0x0003);
+ val = 0x0003;
+ wm8994_write(codec, 0x102, val);
- /* Unmute and volume ctrl RightDAC */
- val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME);
- val &= ~(WM8994_DAC1R_MUTE_MASK | WM8994_DAC1R_VOL_MASK);
- val |= TUNING_DAC1R_VOL;
- wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val);
- }
+ val = wm8994_read(codec, 0x56);
+ val &= ~(0x0003);
+ val = 0x0003;
+ wm8994_write(codec, 0x56, 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);
+ val = wm8994_read(codec, 0x102);
+ val &= ~(0x0000);
+ val = 0x0000;
+ wm8994_write(codec, 0x102, val);
- wm8994_write(codec, 0x36, 0x0003);
- /* Digital Path Enables and Unmutes */
- wm8994_write(codec, 0x520, 0x0000);
- wm8994_write(codec, 0x601, 0x0005);
- wm8994_write(codec, 0x602, 0x0005);
- wm8994_write(codec, 0x603, 0x000C);
- wm8994_write(codec, 0x612, 0x01C0);
- wm8994_write(codec, 0x613, 0x01C0);
- wm8994_write(codec, 0x620, 0x0000);
- wm8994_write(codec, 0x621, 0x01C0);
+ val = wm8994_read(codec, WM8994_CLASS_W_1);
+ val &= ~(0x0005);
+ val |= 0x0005;
+ wm8994_write(codec, WM8994_CLASS_W_1, val);
- /* 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);
+ val = wm8994_read(codec, WM8994_LEFT_OUTPUT_VOLUME);
+ val &= ~(WM8994_HPOUT1L_MUTE_N_MASK | WM8994_HPOUT1L_VOL_MASK);
+ val |= (WM8994_HPOUT1_VU | WM8994_HPOUT1L_MUTE_N |
+ TUNING_CALL_OUTPUTL_VOL);
+ wm8994_write(codec, WM8994_LEFT_OUTPUT_VOLUME, val);
- wm8994_set_voicecall_common_setting(codec);
+ val = wm8994_read(codec, WM8994_RIGHT_OUTPUT_VOLUME);
+ val &= ~(WM8994_HPOUT1R_MUTE_N_MASK | WM8994_HPOUT1R_VOL_MASK);
+ val |= (WM8994_HPOUT1_VU | WM8994_HPOUT1R_MUTE_N |
+ TUNING_CALL_OUTPUTR_VOL);
+ wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, val);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_1,
- WM8994_SPKOUTL_ENA | WM8994_VMID_SEL_NORMAL |
- WM8994_BIAS_ENA);
-}
+ val = wm8994_read(codec, WM8994_DC_SERVO_2);
+ val &= ~(0x03E0);
+ val = 0x03E0;
+ wm8994_write(codec, WM8994_DC_SERVO_2, val);
-void wm8994_set_voicecall_bluetooth(struct snd_soc_codec *codec)
-{
- DEBUG_LOG("");
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, 0x0303);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, 0x0007);
- msleep(50);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, 0x0003);
-
- /*Digital Path Enables and Unmutes */
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, 0x00);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, 0x00);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_4, 0x3000);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_5,
- WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA |
- WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA |
- WM8994_DAC2L_ENA | WM8994_DAC2R_ENA);
- /*
- * 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,
- 0x0003 << WM8994_AIF2_ADCDAT_SRC_SHIFT);
+ wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x0022);
+ wm8994_write(codec, WM8994_CHARGE_PUMP_1, 0x9F25);
- wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, 0x00);
+ msleep(5);
- 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);
+ /* Analogue Output Configuration */
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_1, 0x0001);
+ wm8994_write(codec, WM8994_OUTPUT_MIXER_2, 0x0001);
- wm8994_write(codec, WM8994_DAC2_LEFT_VOLUME, 0x1C0);
- wm8994_write(codec, WM8994_DAC2_RIGHT_VOLUME, 0x1C0);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, 0x0030);
- /*Clocking */
- wm8994_write(codec, WM8994_CLOCKING_1,
- WM8994_DSP_FS1CLK_ENA | WM8994_DSP_FS2CLK_ENA |
- WM8994_DSP_FSINTCLK_ENA);
- wm8994_write(codec, WM8994_AIF2_RATE,
- 0x0003 << WM8994_AIF2CLK_RATE_SHIFT);
+ wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019);
- /*AIF1Interface */
- wm8994_write(codec, WM8994_AIF1_CONTROL_2, 0x0000);
- wm8994_write(codec, WM8994_AIF1_MASTER_SLAVE, WM8994_AIF1_MSTR |
- WM8994_AIF1_CLK_FRC | WM8994_AIF1_LRCLK_FRC);
+ wm8994_write(codec, WM8994_DC_SERVO_1, 0x303);
- /*AIF2 Interface */
- 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);
- wm8994_write(codec, WM8994_AIF2_CONTROL_1,
- WM8994_AIF2ADCR_SRC | WM8994_AIF2_BCLK_INV |
- WM8994_AIF2_LRCLK_INV | 0x1 << WM8994_AIF2_FMT_SHIFT);
+ msleep(160);
- wm8994_write(codec, WM8994_OVERSAMPLING, 0X0000);
+ testreturn1 = wm8994_read(codec, WM8994_DC_SERVO_4);
- /*FLL2 Setting */
- 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_AIF2_CLOCKING_1, 0x0019);
- wm8994_write(codec, WM8994_FLL2_CONTROL_1,
- WM8994_FLL2_FRACN_ENA | WM8994_FLL2_ENA);
+ testlow = (signed char)(testreturn1 & 0xff);
+ testhigh = (signed char)((testreturn1>>8) & 0xff);
- /*GPIO Configuration */
- wm8994_write(codec, WM8994_GPIO_1, 0xA101);
- wm8994_write(codec, WM8994_GPIO_3, WM8994_GP3_DIR | WM8994_GP3_DB);
- wm8994_write(codec, WM8994_GPIO_4, WM8994_GP4_DIR | WM8994_GP4_DB);
- wm8994_write(codec, WM8994_GPIO_5, WM8994_GP5_DIR | WM8994_GP5_DB);
- wm8994_write(codec, WM8994_GPIO_6,
- WM8994_GP6_DIR | WM8994_GP6_PD | WM8994_GP6_DB | 0x1 <<
- WM8994_GP6_FN_SHIFT);
- wm8994_write(codec, WM8994_GPIO_7, WM8994_GP7_DB);
- 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);
-}
+ testlow1 = ((signed short)testlow - 5) & 0x00ff;
+ testhigh1 = (((signed short)(testhigh - 5)<<8) & 0xff00);
+ testreturn2 = testlow1|testhigh1;
+ wm8994_write(codec, WM8994_DC_SERVO_4, testreturn2);
-void wm8994_set_fmradio_common(struct snd_soc_codec *codec)
-{
- struct wm8994_priv *wm8994 = codec->drvdata;
+ val = wm8994_read(codec, WM8994_DC_SERVO_1);
+ val &= ~(0x000F);
+ val = 0x000F;
+ wm8994_write(codec, WM8994_DC_SERVO_1, val);
- u16 val;
+ msleep(15);
- val = wm8994_read(codec, WM8994_LEFT_LINE_INPUT_3_4_VOLUME);
- val &= ~(WM8994_IN2L_VU_MASK);
- val |= (WM8994_IN2L_VU | WM8994_IN2L_VOL_16_5dB);
- wm8994_write(codec, WM8994_LEFT_LINE_INPUT_3_4_VOLUME, 0x0116);
+ wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x00EE);
- val = wm8994_read(codec, WM8994_RIGHT_LINE_INPUT_3_4_VOLUME);
- val &= ~(WM8994_IN2R_VU_MASK);
- val |= (WM8994_IN2R_VU_MASK | WM8994_IN2R_VOL_16_5dB);
- wm8994_write(codec, WM8994_RIGHT_LINE_INPUT_3_4_VOLUME, 0x0116);
+ /* Unmute DAC1 left */
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
+ val &= ~(WM8994_DAC1L_MUTE_MASK | WM8994_DAC1L_VOL_MASK);
+ val |= TUNING_DAC1L_VOL;
+ wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val);
- val = (WM8994_IN2LN_TO_IN2L | WM8994_IN2RN_TO_IN2R);
- wm8994_write(codec, WM8994_INPUT_MIXER_2, val);
+ /* Unmute and volume ctrl RightDAC */
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME);
+ val &= ~(WM8994_DAC1R_MUTE_MASK | WM8994_DAC1R_VOL_MASK);
+ val |= TUNING_DAC1R_VOL;
+ wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val);
- if (!wm8994->testmode_config_flag) {
- /* IN2L to MIXINL */
- val = wm8994_read(codec, WM8994_INPUT_MIXER_3);
- val &= ~(WM8994_IN2L_TO_MIXINL_MASK);
- val |= WM8994_IN2L_TO_MIXINL;
- wm8994_write(codec, WM8994_INPUT_MIXER_3, val);
+ wm8994_write(codec, WM8994_DAC2_LEFT_VOLUME, 0x01C0);
- /* IN2R to MIXINR */
- val = wm8994_read(codec, WM8994_INPUT_MIXER_4);
- val &= ~(WM8994_IN2R_TO_MIXINR_MASK);
- val |= WM8994_IN2R_TO_MIXINR;
- wm8994_write(codec, WM8994_INPUT_MIXER_4, val);
- }
+ wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, 0x0000);
+ wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, 0x0000);
}
-void wm8994_set_fmradio_headset(struct snd_soc_codec *codec)
+void wm8994_set_voicecall_speaker(struct snd_soc_codec *codec)
{
struct wm8994_priv *wm8994 = codec->drvdata;
- u16 val;
-
- u16 nReadServo4Val = NULL;
- u16 ncompensationResult = NULL;
- u16 nServo4Low = NULL;
- u16 nServo4High = NULL;
- u8 nCompensationResultLow = 0;
- u8 nCompensationResultHigh = 0;
-
- DEBUG_LOG("Routing ear path : FM Radio -> EAR Out");
-
- wm8994->fmradio_path = FMR_HP;
-
- /* Disable reg sync to MCLK */
- val = wm8994_read(codec, WM8994_AIF1_CLOCKING_1);
- val &= ~(WM8994_AIF1CLK_ENA_MASK);
- val |= WM8994_AIF1CLK_ENA;
- wm8994_write(codec, WM8994_AIF1_CLOCKING_1, val);
-
- val = wm8994_read(codec, WM8994_CONTROL_INTERFACE);
- val &= ~(WM8994_AUTO_INC_MASK);
- val |= WM8994_AUTO_INC;
- wm8994_write(codec, WM8994_CONTROL_INTERFACE, val);
-
- /* Analogue Path Config */
- val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_2);
- val &= ~(WM8994_MIXINL_ENA_MASK | WM8994_MIXINR_ENA_MASK |
- WM8994_IN2L_ENA_MASK | WM8994_IN2R_ENA_MASK);
- val |= (WM8994_MIXINL_ENA | WM8994_MIXINR_ENA |
- WM8994_IN2L_ENA | WM8994_IN2R_ENA);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, val);
-
- val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1);
- val &= ~(WM8994_BIAS_ENA_MASK | WM8994_VMID_SEL_NORMAL);
- val |= (WM8994_BIAS_ENA | WM8994_VMID_SEL_NORMAL);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, 0x0003);
-
- val = wm8994_read(codec, WM8994_LEFT_OUTPUT_VOLUME);
- val = 0x0000;
- wm8994_write(codec, WM8994_LEFT_OUTPUT_VOLUME, val);
-
- val = wm8994_read(codec, WM8994_RIGHT_OUTPUT_VOLUME);
- val = 0x0000;
- wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, val);
+ int val;
- wm8994_set_fmradio_common(codec);
+ DEBUG_LOG("");
- /* Output mixer setting */
- val = wm8994_read(codec, WM8994_OUTPUT_MIXER_1);
- val &= ~(WM8994_DAC1L_TO_HPOUT1L_MASK | WM8994_MIXINL_TO_MIXOUTL_MASK);
- val |= (WM8994_MIXINL_TO_MIXOUTL);
- wm8994_write(codec, WM8994_OUTPUT_MIXER_1, val);
+ audio_ctrl_mic_bias_gpio(wm8994->pdata, 1);
- val = wm8994_read(codec, WM8994_OUTPUT_MIXER_2);
- val &= ~(WM8994_DAC1R_TO_HPOUT1R_MASK | WM8994_MIXINR_TO_MIXOUTR_MASK);
- val |= (WM8994_MIXINR_TO_MIXOUTR);
- wm8994_write(codec, WM8994_OUTPUT_MIXER_2, val);
+ wm8994_set_voicecall_common_setting(codec);
- /** Headset */
- wm8994_write(codec, 0x102, 0x0003);
- wm8994_write(codec, 0x56, 0x0003);
- wm8994_write(codec, 0x102, 0x0000);
- wm8994_write(codec, 0x5D, 0x0002);
+ 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);
- /* DC Servo Series Count */
- val = 0x03E0;
- wm8994_write(codec, WM8994_DC_SERVO_2, val);
+ /* 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 |
+ WM8994_IN1L_MIXINL_VOL_MASK |
+ WM8994_MIXOUTL_MIXINL_VOL_MASK);
+ val |= (WM8994_IN1L_TO_MIXINL | TUNING_CALL_SPK_MIXER_VOL);
+ 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_IN1L_VOL_MASK);
+ val |= (WM8994_IN1L_VU | TUNING_CALL_SPK_INPUTMIX_VOL);
+ wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME, val);
+
+ /* Analogue Output Configuration*/
+ wm8994_write(codec, 0x03, 0x0300);
- /* HP first and second stage */
- /* 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);
- val |= (WM8994_BIAS_ENA | WM8994_VMID_SEL_NORMAL |
- WM8994_HPOUT1R_ENA | WM8994_HPOUT1L_ENA);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_4,
+ WM8994_AIF2ADCL_ENA | WM8994_ADCL_ENA);
- val = (WM8994_HPOUT1L_DLY | WM8994_HPOUT1R_DLY);
- wm8994_write(codec, WM8994_ANALOGUE_HP_1, val);
+ wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019);
- /* Enable Charge Pump */
- 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, 0x9F25);
+ val = wm8994_read(codec, WM8994_SPKMIXL_ATTENUATION);
+ val &= ~(WM8994_SPKMIXL_VOL_MASK);
+ val |= TUNING_SPKMIXL_ATTEN;
+ wm8994_write(codec, WM8994_SPKMIXL_ATTENUATION, val);
- msleep(5);
+ val = wm8994_read(codec, WM8994_SPKMIXR_ATTENUATION);
+ val &= ~(WM8994_SPKMIXR_VOL_MASK);
+ val |= TUNING_SPKMIXR_ATTEN;
+ wm8994_write(codec, WM8994_SPKMIXR_ATTENUATION, val);
- /* DC Servo */
- val = (WM8994_DCS_TRIG_SERIES_1 | WM8994_DCS_TRIG_SERIES_0 |
- WM8994_DCS_ENA_CHAN_1 | WM8994_DCS_ENA_CHAN_0);
- wm8994_write(codec, WM8994_DC_SERVO_1, 0x0303);
+ val = wm8994_read(codec, WM8994_SPEAKER_VOLUME_LEFT);
+ val &= ~(WM8994_SPKOUTL_MUTE_N_MASK | WM8994_SPKOUTL_VOL_MASK);
+ val |= (WM8994_SPKOUT_VU | WM8994_SPKOUTL_MUTE_N |
+ TUNING_CALL_SPKL_VOL);
+ wm8994_write(codec, WM8994_SPEAKER_VOLUME_LEFT, val);
- msleep(160);
+ 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);
- nReadServo4Val = wm8994_read(codec, WM8994_DC_SERVO_4);
- nServo4Low = (u8) (nReadServo4Val & 0xff);
- nServo4High = (u8) ((nReadServo4Val >> 8) & 0xff);
+ val = wm8994_read(codec, WM8994_CLASSD);
+ val &= ~(WM8994_SPKOUTL_BOOST_MASK);
+ val |= TUNING_CALL_CLASSD_VOL << WM8994_SPKOUTL_BOOST_SHIFT;
+ wm8994_write(codec, WM8994_CLASSD, val);
- nCompensationResultLow = ((u16) nServo4Low - 4) & 0x00ff;
- nCompensationResultHigh = (((u16) nServo4High - 4) << 8) & 0xff00;
- ncompensationResult = nCompensationResultLow | nCompensationResultHigh;
- wm8994_write(codec, WM8994_DC_SERVO_4, ncompensationResult);
+ 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);
- val = (WM8994_DCS_TRIG_DAC_WR_1 | WM8994_DCS_TRIG_DAC_WR_0 |
- WM8994_DCS_ENA_CHAN_1 | WM8994_DCS_ENA_CHAN_0);
- wm8994_write(codec, WM8994_DC_SERVO_1, val);
+ wm8994_write(codec, 0x36, 0x0003);
+ /* Digital Path Enables and Unmutes*/
- msleep(20);
+ wm8994_write(codec, WM8994_SIDETONE, 0x01C0);
- /* Headphone Output */
- /* 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);
-
- /* Enable MIXOUT */
- 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_MIXOUTLVOL_ENA | WM8994_MIXOUTRVOL_ENA |
- WM8994_MIXOUTL_ENA | WM8994_MIXOUTR_ENA);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, val);
- /* Unmutes */
- /* Output setting */
- if (!wm8994->testmode_config_flag) {
- val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME);
- val &= ~(WM8994_MIXOUTL_MUTE_N_MASK | WM8994_MIXOUTL_VOL_MASK);
- val |= (WM8994_MIXOUT_VU | WM8994_MIXOUTL_MUTE_N |
- TUNING_FMRADIO_OPGAL_VOL);
- wm8994_write(codec, WM8994_LEFT_OPGA_VOLUME, val);
+ wm8994_write(codec, WM8994_ANALOGUE_HP_1, 0x0000);
+ wm8994_write(codec, WM8994_DC_SERVO_1, 0x0000);
- val = wm8994_read(codec, WM8994_RIGHT_OPGA_VOLUME);
- val &= ~(WM8994_MIXOUTR_MUTE_N_MASK | WM8994_MIXOUTR_VOL_MASK);
- val |= (WM8994_MIXOUT_VU | WM8994_MIXOUTR_MUTE_N |
- TUNING_FMRADIO_OPGAR_VOL);
- wm8994_write(codec, WM8994_RIGHT_OPGA_VOLUME, val);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1,
+ WM8994_SPKOUTL_ENA | WM8994_VMID_SEL_NORMAL | WM8994_BIAS_ENA);
- val = wm8994_read(codec, WM8994_LEFT_OUTPUT_VOLUME);
- val &= ~(WM8994_HPOUT1L_MUTE_N_MASK | WM8994_HPOUT1L_VOL_MASK);
- val |= (WM8994_HPOUT1_VU | WM8994_HPOUT1L_MUTE_N |
- TUNING_FMRADIO_OUTPUTL_VOL);
- wm8994_write(codec, WM8994_LEFT_OUTPUT_VOLUME, val);
+ /* Unmute DAC1 left */
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
+ val &= ~(WM8994_DAC1L_MUTE_MASK | WM8994_DAC1L_VOL_MASK);
+ val |= TUNING_DAC1L_VOL;
+ wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val);
- val = wm8994_read(codec, WM8994_RIGHT_OUTPUT_VOLUME);
- val &= ~(WM8994_HPOUT1R_MUTE_N_MASK | WM8994_HPOUT1R_VOL_MASK);
- val |= (WM8994_HPOUT1_VU | WM8994_HPOUT1R_MUTE_N |
- TUNING_FMRADIO_OUTPUTR_VOL);
- wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, val);
- }
+ /* Unmute and volume ctrl RightDAC */
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME);
+ val &= ~(WM8994_DAC1R_MUTE_MASK | WM8994_DAC1R_VOL_MASK);
+ val |= TUNING_DAC1R_VOL;
+ 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_fmradio_speaker(struct snd_soc_codec *codec)
+void wm8994_set_voicecall_bluetooth(struct snd_soc_codec *codec)
{
- struct wm8994_priv *wm8994 = codec->drvdata;
+ int val;
- u16 val;
+ DEBUG_LOG("");
- DEBUG_LOG("Routing spk path : FM Radio -> SPK Out");
+ wm8994_set_voicecall_common_setting(codec);
- wm8994->fmradio_path = FMR_SPK;
+ /* 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);
- /* Disable end point for preventing pop up noise. */
- val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1);
- val &= ~(WM8994_SPKOUTL_ENA_MASK);
+ /* 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);
- val = (WM8994_TSHUT_ENA | WM8994_TSHUT_OPDIS | WM8994_OPCLK_ENA |
- WM8994_MIXINL_ENA | WM8994_MIXINR_ENA | WM8994_IN2L_ENA |
- WM8994_IN2R_ENA);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_2, val);
-
- wm8994_set_fmradio_common(codec);
-
- if (!wm8994->testmode_config_flag) {
- /* Unmute the SPKMIXVOLUME */
- val = wm8994_read(codec, WM8994_SPKMIXL_ATTENUATION);
- val &= ~(WM8994_SPKMIXL_VOL_MASK);
- val |= TUNING_SPKMIXL_ATTEN;
- wm8994_write(codec, WM8994_SPKMIXL_ATTENUATION, val);
-
- val = wm8994_read(codec, WM8994_SPKMIXR_ATTENUATION);
- val &= ~(WM8994_SPKMIXR_VOL_MASK);
- wm8994_write(codec, WM8994_SPKMIXR_ATTENUATION, val);
-
- val = wm8994_read(codec, WM8994_SPEAKER_VOLUME_LEFT);
- val &= ~(WM8994_SPKOUTL_MUTE_N_MASK | WM8994_SPKOUTL_VOL_MASK);
- val |= (WM8994_SPKOUT_VU | WM8994_SPKOUTL_MUTE_N |
- TUNING_FMRADIO_SPKL_VOL);
- 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_CLASSD);
- val &= ~(WM8994_SPKOUTL_BOOST_MASK);
- val |= TUNING_FMRADIO_CLASSD_VOL << WM8994_SPKOUTL_BOOST_SHIFT;
- wm8994_write(codec, WM8994_CLASSD, val);
-
- }
-
- /*Output MIxer-Output PGA */
- 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, WM8994_POWER_MANAGEMENT_4,
+ WM8994_AIF2ADCL_ENA | WM8994_ADCL_ENA);
- /* Output mixer setting */
- val = wm8994_read(codec, WM8994_SPEAKER_MIXER);
- val &= ~(WM8994_MIXINL_TO_SPKMIXL_MASK | WM8994_MIXINR_TO_SPKMIXR_MASK);
- val |= (WM8994_MIXINL_TO_SPKMIXL);
- wm8994_write(codec, WM8994_SPEAKER_MIXER, val);
+ /* 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);
- /* Enable SPK Volume. */
- val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_3);
- val &= ~(WM8994_SPKRVOL_ENA_MASK | WM8994_SPKLVOL_ENA_MASK);
- val |= (WM8994_SPKLVOL_ENA);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_3, val);
+ /*
+ * for BT DTMF Play
+ * Rx Path: AIF2ADCDAT2 select
+ * CP(CALL) Path:GPIO5/DACDAT2 select
+ * AP(DTMF) Path: DACDAT1 select
+ * Tx Path: GPIO8/DACDAT3 select
+ */
- /* Enbale bias,vmid and Left speaker */
- val = wm8994_read(codec, WM8994_POWER_MANAGEMENT_1);
- val &= ~(WM8994_BIAS_ENA_MASK | WM8994_VMID_SEL_MASK |
- WM8994_SPKOUTL_ENA_MASK);
- val |= (WM8994_BIAS_ENA | WM8994_VMID_SEL_NORMAL | WM8994_SPKOUTL_ENA);
- wm8994_write(codec, WM8994_POWER_MANAGEMENT_1, val);
-}
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_6, 0x000C);
-void wm8994_set_fmradio_headset_mix(struct snd_soc_codec *codec)
-{
- struct wm8994_priv *wm8994 = codec->drvdata;
+ /* 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);
- DEBUG_LOG("");
+ wm8994_write(codec, WM8994_AIF2_CLOCKING_1, 0x0019);
- wm8994->fmradio_path = FMR_HP_MIX;
+ wm8994_write(codec, WM8994_DAC2_MIXER_VOLUMES, 0x000C);
- wm8994_set_playback_headset(codec);
- wm8994_set_fmradio_headset(codec);
-}
+ wm8994_write(codec, WM8994_DAC2_LEFT_VOLUME, 0x01C0);
+ wm8994_write(codec, WM8994_DAC2_RIGHT_VOLUME, 0x01C0);
-void wm8994_set_fmradio_speaker_mix(struct snd_soc_codec *codec)
-{
- struct wm8994_priv *wm8994 = codec->drvdata;
+ wm8994_write(codec, WM8994_OVERSAMPLING, 0X0000);
- DEBUG_LOG("");
+ /* Unmute DAC1 left */
+ val = wm8994_read(codec, WM8994_DAC1_LEFT_VOLUME);
+ val &= ~(WM8994_DAC1L_MUTE_MASK | WM8994_DAC1L_VOL_MASK);
+ val |= TUNING_DAC1L_VOL;
+ wm8994_write(codec, WM8994_DAC1_LEFT_VOLUME, val);
- wm8994->fmradio_path = FMR_SPK_MIX;
+ /* Unmute and volume ctrl RightDAC */
+ val = wm8994_read(codec, WM8994_DAC1_RIGHT_VOLUME);
+ val &= ~(WM8994_DAC1R_MUTE_MASK | WM8994_DAC1R_VOL_MASK);
+ val |= TUNING_DAC1R_VOL;
+ wm8994_write(codec, WM8994_DAC1_RIGHT_VOLUME, val);
- wm8994_set_fmradio_speaker(codec);
- wm8994_set_playback_headset(codec);
+ wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, 0x0000);
+ wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, 0x0000);
}
-void wm8994_set_fmradio_speaker_headset_mix(struct snd_soc_codec *codec)
-{
- struct wm8994_priv *wm8994 = codec->drvdata;
-
- DEBUG_LOG("");
-
- wm8994->fmradio_path = FMR_SPK_HP_MIX;
-
- wm8994_set_playback_speaker_headset(codec);
- wm8994_set_fmradio_headset(codec);
-}
diff --git a/sound/soc/codecs/wm8994_samsung.c b/sound/soc/codecs/wm8994_samsung.c
new file mode 100755
index 0000000..d899ab8
--- /dev/null
+++ b/sound/soc/codecs/wm8994_samsung.c
@@ -0,0 +1,1528 @@
+/*
+ * wm8994_samsung.c -- WM8994 ALSA Soc Audio driver
+ *
+ * Copyright 2010 Wolfson Microelectronics PLC.
+ *
+ * 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.
+ *
+ * Notes:
+ * The WM8994 is a multichannel codec with S/PDIF support, featuring six
+ * DAC channels and two ADC channels.
+ *
+ * Currently only the primary audio interface is supported - S/PDIF and
+ * the secondary audio interfaces are not.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <sound/initval.h>
+#include <asm/div64.h>
+#include <linux/io.h>
+#include <plat/map-base.h>
+#include <linux/gpio.h>
+#include <plat/gpio-cfg.h>
+#include <mach/regs-clock.h>
+#include "wm8994_samsung.h"
+
+#define WM8994_VERSION "0.1"
+#define SUBJECT "wm8994_samsung.c"
+
+#if defined(CONFIG_VIDEO_TV20) && defined(CONFIG_SND_S5P_WM8994_MASTER)
+#define HDMI_USE_AUDIO
+#endif
+
+/*
+ *Definitions of clock related.
+*/
+
+static struct {
+ int ratio;
+ int clk_sys_rate;
+} clk_sys_rates[] = {
+ { 64, 0 },
+ { 128, 1 },
+ { 192, 2 },
+ { 256, 3 },
+ { 384, 4 },
+ { 512, 5 },
+ { 768, 6 },
+ { 1024, 7 },
+ { 1408, 8 },
+ { 1536, 9 },
+};
+
+static struct {
+ int rate;
+ int sample_rate;
+} sample_rates[] = {
+ { 8000, 0 },
+ { 11025, 1 },
+ { 12000, 2 },
+ { 16000, 3 },
+ { 22050, 4 },
+ { 24000, 5 },
+ { 32000, 6 },
+ { 44100, 7 },
+ { 48000, 8 },
+ { 88200, 9 },
+ { 96000, 10 },
+};
+
+static struct {
+ int div;
+ int bclk_div;
+} bclk_divs[] = {
+ { 1, 0 },
+ { 2, 1 },
+ { 4, 2 },
+ { 6, 3 },
+ { 8, 4 },
+ { 12, 5 },
+ { 16, 6 },
+ { 24, 7 },
+ { 32, 8 },
+ { 48, 9 },
+};
+
+struct snd_soc_dai wm8994_dai;
+EXPORT_SYMBOL_GPL(wm8994_dai);
+
+struct snd_soc_codec_device soc_codec_dev_pcm_wm8994;
+EXPORT_SYMBOL_GPL(soc_codec_dev_pcm_wm8994);
+
+struct snd_soc_codec_device soc_codec_dev_wm8994;
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm8994);
+
+static struct wm8994_platform_data *pdata;
+
+static void wm8994_set_off(struct snd_soc_codec *codec);
+
+/*
+ * Definitions of sound path
+ */
+select_route universal_wm8994_playback_paths[] = {
+ wm8994_set_off, wm8994_set_playback_receiver,
+ wm8994_set_playback_speaker, wm8994_set_playback_headset,
+ wm8994_set_off, wm8994_set_playback_speaker_headset
+};
+
+select_route universal_wm8994_voicecall_paths[] = {
+ wm8994_set_off, wm8994_set_voicecall_receiver,
+ wm8994_set_voicecall_speaker, wm8994_set_voicecall_headset,
+ wm8994_set_voicecall_bluetooth
+};
+
+select_mic_route universal_wm8994_mic_paths[] = {
+ wm8994_record_main_mic, wm8994_record_headset_mic,
+};
+
+select_clock_control universal_clock_controls = wm8994_configure_clock;
+
+/*
+ * Implementation of I2C functions
+ */
+static unsigned int wm8994_read_hw(struct snd_soc_codec *codec, u16 reg)
+{
+ struct i2c_msg xfer[2];
+ u16 data;
+ int ret;
+ struct i2c_client *i2c = codec->control_data;
+
+ data = ((reg & 0xff00) >> 8) | ((reg & 0xff) << 8);
+
+ xfer[0].addr = i2c->addr;
+ xfer[0].flags = 0;
+ xfer[0].len = 2;
+ xfer[0].buf = (void *)&data;
+
+ xfer[1].addr = i2c->addr;
+ xfer[1].flags = I2C_M_RD;
+ xfer[1].len = 2;
+ xfer[1].buf = (u8 *)&data;
+ ret = i2c_transfer(i2c->adapter, xfer, 2);
+ if (ret != 2) {
+ dev_err(codec->dev, "Failed to read 0x%x: %d\n", reg, ret);
+ return 0;
+ }
+
+ return (data >> 8) | ((data & 0xff) << 8);
+}
+
+int wm8994_write(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned int value)
+{
+ u8 data[4];
+ int ret;
+
+ /* data is
+ * D15..D9 WM8993 register offset
+ * D8...D0 register data
+ */
+ data[0] = (reg & 0xff00) >> 8;
+ data[1] = reg & 0x00ff;
+ data[2] = value >> 8;
+ data[3] = value & 0x00ff;
+ ret = codec->hw_write(codec->control_data, data, 4);
+
+ if (ret == 4)
+ return 0;
+ else {
+ pr_err("i2c write problem occured\n");
+ return ret;
+ }
+}
+
+inline unsigned int wm8994_read(struct snd_soc_codec *codec, unsigned int reg)
+{
+ return wm8994_read_hw(codec, reg);
+}
+
+static int wm8994_ldo_control(struct wm8994_platform_data *pdata, int en)
+{
+
+ if (!pdata) {
+ pr_err("failed to control wm8994 ldo\n");
+ return -EINVAL;
+ }
+
+ gpio_set_value(pdata->ldo, en);
+
+ if (en)
+ msleep(10);
+ else
+ msleep(125);
+
+ return 0;
+
+}
+
+/*
+ * Functions related volume.
+ */
+static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
+
+static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ret;
+ u16 val;
+
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ int reg = mc->reg;
+
+ DEBUG_LOG("");
+
+ ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
+ if (ret < 0)
+ return ret;
+
+ val = wm8994_read(codec, reg);
+
+ return wm8994_write(codec, reg, val | 0x0100);
+}
+
+static int wm899x_inpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ int reg = mc->reg;
+ int ret;
+ u16 val;
+
+ ret = snd_soc_put_volsw(kcontrol, ucontrol);
+
+ if (ret < 0)
+ return ret;
+
+ val = wm8994_read(codec, reg);
+
+ return wm8994_write(codec, reg, val | 0x0100);
+
+}
+
+/*
+ * Implementation of sound path
+ */
+#define MAX_PLAYBACK_PATHS 8
+#define MAX_VOICECALL_PATH 4
+static const char *playback_path[] = {
+ "OFF", "RCV", "SPK", "HP", "BT", "SPK_HP",
+ "RING_SPK", "RING_HP", "RING_SPK_HP"
+};
+static const char *voicecall_path[] = { "OFF", "RCV", "SPK", "HP", "BT" };
+static const char *mic_path[] = { "Main Mic", "Hands Free Mic" };
+static const char *mic_state[] = { "MIC_NO_USE", "MIC_USE" };
+
+static int wm8994_get_mic_path(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm8994_priv *wm8994 = codec->drvdata;
+
+ ucontrol->value.integer.value[0] = wm8994->rec_path;
+
+ return 0;
+}
+
+static int wm8994_set_mic_path(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm8994_priv *wm8994 = codec->drvdata;
+
+ DEBUG_LOG("");
+
+ if (ucontrol->value.integer.value[0] == 0)
+ wm8994->rec_path = MAIN;
+ else if (ucontrol->value.integer.value[0] == 1)
+ wm8994->rec_path = SUB;
+ else if (ucontrol->value.integer.value[0] == 2) {
+ wm8994->rec_path = BT_REC;
+ wm8994->universal_mic_path[wm8994->rec_path] (codec);
+ return 0;
+ } else
+ return -EINVAL;
+
+ wm8994->universal_mic_path[wm8994->rec_path] (codec);
+
+ return 0;
+}
+
+static int wm8994_get_path(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm8994_priv *wm8994 = codec->drvdata;
+
+ ucontrol->value.integer.value[0] = wm8994->cur_path;
+
+ return 0;
+}
+
+static int wm8994_set_path(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm8994_priv *wm8994 = codec->drvdata;
+ struct soc_enum *mc = (struct soc_enum *)kcontrol->private_value;
+
+ int path_num = ucontrol->value.integer.value[0];
+
+ if (strcmp(mc->texts[path_num], playback_path[path_num])) {
+ DEBUG_LOG_ERR("Unknown path %s\n", mc->texts[path_num]);
+ return -ENODEV;
+ }
+
+ if (path_num > MAX_PLAYBACK_PATHS) {
+ DEBUG_LOG_ERR("Unknown Path\n");
+ return -ENODEV;
+ }
+
+ switch (path_num) {
+ case OFF:
+ DEBUG_LOG("Switching off output path\n");
+ break;
+ case RCV:
+ case SPK:
+ case HP:
+ case SPK_HP:
+ case BT:
+ DEBUG_LOG("routing to %s\n", mc->texts[path_num]);
+ wm8994->ringtone_active = DEACTIVE;
+ break;
+ case RING_SPK:
+ case RING_HP:
+ DEBUG_LOG("routing to %s\n", mc->texts[path_num]);
+ wm8994->ringtone_active = ACTIVE;
+ path_num -= 4;
+ break;
+ case RING_SPK_HP:
+ DEBUG_LOG("routing to %s\n", mc->texts[path_num]);
+ wm8994->ringtone_active = ACTIVE;
+ path_num -= 3;
+ break;
+ default:
+ DEBUG_LOG_ERR("audio path[%d] does not exists!!\n", path_num);
+ return -ENODEV;
+ break;
+ }
+
+ wm8994->cur_path = path_num;
+ wm8994->call_state = DISCONNECT;
+ wm8994->universal_playback_path[wm8994->cur_path] (codec);
+
+ return 0;
+}
+
+static int wm8994_get_voice_path(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm8994_priv *wm8994 = codec->drvdata;
+
+ ucontrol->value.integer.value[0] = wm8994->cur_path;
+
+ return 0;
+}
+
+static int wm8994_set_voice_path(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm8994_priv *wm8994 = codec->drvdata;
+ struct soc_enum *mc = (struct soc_enum *)kcontrol->private_value;
+
+ int path_num = ucontrol->value.integer.value[0];
+
+ if (strcmp(mc->texts[path_num], voicecall_path[path_num])) {
+ DEBUG_LOG_ERR("Unknown path %s\n", mc->texts[path_num]);
+ return -ENODEV;
+ }
+
+ switch (path_num) {
+ case OFF:
+ DEBUG_LOG("Switching off output path\n");
+ break;
+ case RCV:
+ case SPK:
+ case HP:
+ case BT:
+ DEBUG_LOG("routing voice path to %s\n", mc->texts[path_num]);
+ break;
+ default:
+ DEBUG_LOG_ERR("path[%d] does not exists!\n", path_num);
+ return -ENODEV;
+ break;
+ }
+
+ if (wm8994->cur_path != path_num || wm8994->call_state == DISCONNECT) {
+ wm8994->cur_path = path_num;
+ wm8994->call_state = CONNECT;
+ wm8994->universal_voicecall_path[wm8994->cur_path] (codec);
+ } else {
+ int val;
+ val = wm8994_read(codec, WM8994_AIF1_DAC1_FILTERS_1);
+ val &= ~(WM8994_AIF1DAC1_MUTE_MASK);
+ val |= (WM8994_AIF1DAC1_UNMUTE);
+ wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, val);
+ }
+
+ return 0;
+}
+
+static int wm8994_get_mic_status(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm8994_priv *wm8994 = codec->drvdata;
+
+ DEBUG_LOG("mic_state = [%d]", wm8994->mic_state);
+
+ return wm8994->mic_state;
+}
+
+static int wm8994_set_mic_status(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm8994_priv *wm8994 = codec->drvdata;
+
+ int control_flag = ucontrol->value.integer.value[0];
+
+ DEBUG_LOG("Changed mic state [%d] => [%d]",
+ wm8994->mic_state, control_flag);
+
+ wm8994->mic_state = control_flag;
+
+ return 0;
+}
+
+static void wm8994_set_off(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = codec->drvdata;
+
+ DEBUG_LOG("");
+
+ wm8994_ldo_control(wm8994->pdata, 0);
+
+ wm8994->universal_clock_control(codec, CODEC_OFF);
+}
+
+#define SOC_WM899X_OUTPGA_DOUBLE_R_TLV(xname, reg_left, reg_right,\
+ xshift, xmax, xinvert, tlv_array) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
+ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
+ SNDRV_CTL_ELEM_ACCESS_READWRITE,\
+ .tlv.p = (tlv_array), \
+ .info = snd_soc_info_volsw_2r, \
+ .get = snd_soc_get_volsw_2r, .put = wm899x_outpga_put_volsw_vu, \
+ .private_value = (unsigned long)&(struct soc_mixer_control) \
+ {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
+ .max = xmax, .invert = xinvert} }
+
+#define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\
+ tlv_array) {\
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
+ SNDRV_CTL_ELEM_ACCESS_READWRITE,\
+ .tlv.p = (tlv_array), \
+ .info = snd_soc_info_volsw, \
+ .get = snd_soc_get_volsw, .put = wm899x_inpga_put_volsw_vu, \
+ .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
+
+static const DECLARE_TLV_DB_SCALE(digital_tlv, -7162, 37, 1);
+static const DECLARE_TLV_DB_LINEAR(digital_tlv_spkr, -5700, 600);
+static const DECLARE_TLV_DB_LINEAR(digital_tlv_rcv, -5700, 600);
+static const DECLARE_TLV_DB_LINEAR(digital_tlv_headphone, -5700, 600);
+static const DECLARE_TLV_DB_LINEAR(digital_tlv_mic, -7162, 7162);
+
+static const struct soc_enum path_control_enum[] = {
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(playback_path), playback_path),
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(voicecall_path), voicecall_path),
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mic_path), mic_path),
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mic_state), mic_state),
+};
+
+static const struct snd_kcontrol_new wm8994_snd_controls[] = {
+ SOC_WM899X_OUTPGA_DOUBLE_R_TLV("Playback Volume",
+ WM8994_LEFT_OPGA_VOLUME,
+ WM8994_RIGHT_OPGA_VOLUME, 0, 0x3F, 0,
+ digital_tlv_rcv),
+ SOC_WM899X_OUTPGA_DOUBLE_R_TLV("Playback Spkr Volume",
+ WM8994_SPEAKER_VOLUME_LEFT,
+ WM8994_SPEAKER_VOLUME_RIGHT, 1, 0x3F, 0,
+ digital_tlv_spkr),
+ SOC_WM899X_OUTPGA_DOUBLE_R_TLV("Playback Headset Volume",
+ WM8994_LEFT_OUTPUT_VOLUME,
+ WM8994_RIGHT_OUTPUT_VOLUME, 1, 0x3F, 0,
+ digital_tlv_headphone),
+ SOC_WM899X_OUTPGA_SINGLE_R_TLV("Capture Volume",
+ WM8994_AIF1_ADC1_LEFT_VOLUME,
+ 0, 0xEF, 0, digital_tlv_mic),
+ /* Path Control */
+ SOC_ENUM_EXT("Playback Path", path_control_enum[0],
+ wm8994_get_path, wm8994_set_path),
+
+ SOC_ENUM_EXT("Voice Call Path", path_control_enum[1],
+ wm8994_get_voice_path, wm8994_set_voice_path),
+
+ SOC_ENUM_EXT("MIC Path", path_control_enum[2],
+ wm8994_get_mic_path, wm8994_set_mic_path),
+
+#if defined USE_INFINIEON_EC_FOR_VT
+ SOC_ENUM_EXT("Clock Control", clock_control_enum[0],
+ s3c_pcmdev_get_clock, s3c_pcmdev_set_clock),
+#endif
+ SOC_ENUM_EXT("Mic Status", path_control_enum[3],
+ wm8994_get_mic_status, wm8994_set_mic_status),
+
+};
+
+/* Add non-DAPM controls */
+static int wm8994_add_controls(struct snd_soc_codec *codec)
+{
+ int err, i;
+
+ for (i = 0; i < ARRAY_SIZE(wm8994_snd_controls); i++) {
+ err = snd_ctl_add(codec->card,
+ snd_soc_cnew(&wm8994_snd_controls[i],
+ codec, NULL));
+ if (err < 0)
+ return err;
+ }
+ return 0;
+}
+static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = {
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+};
+
+static int wm8994_add_widgets(struct snd_soc_codec *codec)
+{
+ snd_soc_dapm_new_controls(codec, wm8994_dapm_widgets,
+ ARRAY_SIZE(wm8994_dapm_widgets));
+
+ snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+ snd_soc_dapm_new_widgets(codec);
+ return 0;
+}
+
+static int configure_clock(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = codec->drvdata;
+ unsigned int reg;
+
+ DEBUG_LOG("");
+
+ reg = wm8994_read(codec, WM8994_AIF1_CLOCKING_1);
+ reg &= ~WM8994_AIF1CLK_ENA;
+ reg &= ~WM8994_AIF1CLK_SRC_MASK;
+ wm8994_write(codec, WM8994_AIF1_CLOCKING_1, reg);
+
+ switch (wm8994->sysclk_source) {
+ case WM8994_SYSCLK_MCLK:
+ dev_dbg(codec->dev, "Using %dHz MCLK\n", wm8994->mclk_rate);
+
+ reg = wm8994_read(codec, WM8994_AIF1_CLOCKING_1);
+ reg &= ~WM8994_AIF1CLK_ENA;
+ wm8994_write(codec, WM8994_AIF1_CLOCKING_1, reg);
+
+ reg = wm8994_read(codec, WM8994_AIF1_CLOCKING_1);
+ reg &= 0x07;
+
+ if (wm8994->mclk_rate > 13500000) {
+ reg |= WM8994_AIF1CLK_DIV;
+ wm8994->sysclk_rate = wm8994->mclk_rate / 2;
+ } else {
+ reg &= ~WM8994_AIF1CLK_DIV;
+ wm8994->sysclk_rate = wm8994->mclk_rate;
+ }
+ reg |= WM8994_AIF1CLK_ENA;
+ wm8994_write(codec, WM8994_AIF1_CLOCKING_1, reg);
+
+ /* Enable clocks to the Audio core and sysclk of wm8994 */
+ reg = wm8994_read(codec, WM8994_CLOCKING_1);
+ reg &= ~(WM8994_SYSCLK_SRC_MASK | WM8994_DSP_FSINTCLK_ENA_MASK
+ | WM8994_DSP_FS1CLK_ENA_MASK);
+ reg |= (WM8994_DSP_FS1CLK_ENA | WM8994_DSP_FSINTCLK_ENA);
+ wm8994_write(codec, WM8994_CLOCKING_1, reg);
+ break;
+
+ case WM8994_SYSCLK_FLL:
+ switch (wm8994->fs) {
+ case 8000:
+ wm8994_write(codec, WM8994_FLL1_CONTROL_2, 0x2F00);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_3, 0x3126);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_4, 0x0100);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_5, 0x0C88);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_1,
+ WM8994_FLL1_FRACN_ENA | WM8994_FLL1_ENA);
+ break;
+
+ case 11025:
+ wm8994_write(codec, WM8994_FLL1_CONTROL_2, 0x1F00);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_3, 0x86C2);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_5, 0x0C88);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_4, 0x00e0);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_1,
+ WM8994_FLL1_FRACN_ENA | WM8994_FLL1_ENA);
+ break;
+
+ case 12000:
+ wm8994_write(codec, WM8994_FLL1_CONTROL_2, 0x1F00);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_3, 0x3126);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_5, 0x0C88);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_4, 0x0100);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_1,
+ WM8994_FLL1_FRACN_ENA | WM8994_FLL1_ENA);
+ break;
+
+ case 16000:
+ wm8994_write(codec, WM8994_FLL1_CONTROL_2, 0x1900);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_3, 0xE23E);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_5, 0x0C88);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_4, 0x0100);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_1,
+ WM8994_FLL1_FRACN_ENA | WM8994_FLL1_ENA);
+ break;
+
+ case 22050:
+ wm8994_write(codec, WM8994_FLL1_CONTROL_2, 0x0F00);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_3, 0x86C2);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_5, 0x0C88);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_4, 0x00E0);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_1,
+ WM8994_FLL1_FRACN_ENA | WM8994_FLL1_ENA);
+ break;
+
+ case 24000:
+ wm8994_write(codec, WM8994_FLL1_CONTROL_2, 0x0F00);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_3, 0x3126);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_5, 0x0C88);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_4, 0x0100);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_1,
+ WM8994_FLL1_FRACN_ENA | WM8994_FLL1_ENA);
+ break;
+
+ case 32000:
+ wm8994_write(codec, WM8994_FLL1_CONTROL_2, 0x0C00);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_3, 0xE23E);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_5, 0x0C88);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_4, 0x0100);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_1,
+ WM8994_FLL1_FRACN_ENA | WM8994_FLL1_ENA);
+ break;
+
+ case 44100:
+ wm8994_write(codec, WM8994_FLL1_CONTROL_2, 0x0700);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_3, 0x86C2);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_5, 0x0C88);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_4, 0x00E0);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_1,
+ WM8994_FLL1_FRACN_ENA | WM8994_FLL1_ENA);
+ break;
+
+ case 48000:
+ wm8994_write(codec, WM8994_FLL1_CONTROL_2, 0x0700);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_3, 0x3126);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_5, 0x0C88);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_4, 0x0100);
+ wm8994_write(codec, WM8994_FLL1_CONTROL_1,
+ WM8994_FLL1_FRACN_ENA | WM8994_FLL1_ENA);
+ break;
+
+ default:
+ DEBUG_LOG_ERR("Unsupported Frequency\n");
+ break;
+ }
+
+ reg = wm8994_read(codec, WM8994_AIF1_CLOCKING_1);
+ reg |= WM8994_AIF1CLK_ENA;
+ reg |= WM8994_AIF1CLK_SRC_FLL1;
+ wm8994_write(codec, WM8994_AIF1_CLOCKING_1, reg);
+
+ /* Enable clocks to the Audio core and sysclk of wm8994*/
+ reg = wm8994_read(codec, WM8994_CLOCKING_1);
+ reg &= ~(WM8994_SYSCLK_SRC_MASK | WM8994_DSP_FSINTCLK_ENA_MASK |
+ WM8994_DSP_FS1CLK_ENA_MASK);
+ reg |= (WM8994_DSP_FS1CLK_ENA | WM8994_DSP_FSINTCLK_ENA);
+ wm8994_write(codec, WM8994_CLOCKING_1, reg);
+ break;
+
+ default:
+ dev_err(codec->dev, "System clock not configured\n");
+ return -EINVAL;
+ }
+
+ dev_dbg(codec->dev, "CLK_SYS is %dHz\n", wm8994->sysclk_rate);
+
+ return 0;
+}
+
+static int wm8994_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ DEBUG_LOG("");
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ case SND_SOC_BIAS_PREPARE:
+ /* VMID=2*40k */
+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
+ WM8994_VMID_SEL_MASK, 0x2);
+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_2,
+ WM8994_TSHUT_ENA, WM8994_TSHUT_ENA);
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
+ if (codec->bias_level == SND_SOC_BIAS_OFF) {
+ /* Bring up VMID with fast soft start */
+ snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+ WM8994_STARTUP_BIAS_ENA |
+ WM8994_VMID_BUF_ENA |
+ WM8994_VMID_RAMP_MASK |
+ WM8994_BIAS_SRC,
+ WM8994_STARTUP_BIAS_ENA |
+ WM8994_VMID_BUF_ENA |
+ WM8994_VMID_RAMP_MASK |
+ WM8994_BIAS_SRC);
+ /* VMID=2*40k */
+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
+ WM8994_VMID_SEL_MASK |
+ WM8994_BIAS_ENA,
+ WM8994_BIAS_ENA | 0x2);
+
+ /* Switch to normal bias */
+ snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+ WM8994_BIAS_SRC |
+ WM8994_STARTUP_BIAS_ENA, 0);
+ }
+
+ /* VMID=2*240k */
+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
+ WM8994_VMID_SEL_MASK, 0x4);
+
+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_2,
+ WM8994_TSHUT_ENA, 0);
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
+ WM8994_LINEOUT_VMID_BUF_ENA, 0);
+
+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
+ WM8994_VMID_SEL_MASK | WM8994_BIAS_ENA, 0);
+ break;
+ }
+
+ codec->bias_level = level;
+
+ return 0;
+}
+
+static int wm8994_set_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct wm8994_priv *wm8994 = codec->drvdata;
+
+ DEBUG_LOG("clk_id =%d ", clk_id);
+
+ switch (clk_id) {
+ case WM8994_SYSCLK_MCLK:
+ wm8994->mclk_rate = freq;
+ wm8994->sysclk_source = clk_id;
+ break;
+ case WM8994_SYSCLK_FLL:
+ wm8994->sysclk_rate = freq;
+ wm8994->sysclk_source = clk_id;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct wm8994_priv *wm8994 = codec->drvdata;
+
+ unsigned int aif1 = wm8994_read(codec, WM8994_AIF1_CONTROL_1);
+ unsigned int aif2 = wm8994_read(codec, WM8994_AIF1_MASTER_SLAVE);
+
+ DEBUG_LOG("");
+
+ aif1 &= ~(WM8994_AIF1_LRCLK_INV | WM8994_AIF1_BCLK_INV |
+ WM8994_AIF1_WL_MASK | WM8994_AIF1_FMT_MASK);
+
+ aif2 &= ~(WM8994_AIF1_LRCLK_FRC_MASK |
+ WM8994_AIF1_CLK_FRC | WM8994_AIF1_MSTR);
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ wm8994->master = 0;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFM:
+ aif2 |= (WM8994_AIF1_MSTR | WM8994_AIF1_LRCLK_FRC);
+ wm8994->master = 1;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFS:
+ aif2 |= (WM8994_AIF1_MSTR | WM8994_AIF1_CLK_FRC);
+ wm8994->master = 1;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+ aif2 |= (WM8994_AIF1_MSTR | WM8994_AIF1_CLK_FRC |
+ WM8994_AIF1_LRCLK_FRC);
+ wm8994->master = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_DSP_B:
+ aif1 |= WM8994_AIF1_LRCLK_INV;
+ case SND_SOC_DAIFMT_DSP_A:
+ aif1 |= 0x18;
+ break;
+ case SND_SOC_DAIFMT_I2S:
+ aif1 |= 0x10;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ aif1 |= 0x8;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_DSP_A:
+ case SND_SOC_DAIFMT_DSP_B:
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ aif1 |= WM8994_AIF1_BCLK_INV;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+
+ case SND_SOC_DAIFMT_I2S:
+ case SND_SOC_DAIFMT_RIGHT_J:
+ case SND_SOC_DAIFMT_LEFT_J:
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ aif1 |= WM8994_AIF1_BCLK_INV | WM8994_AIF1_LRCLK_INV;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ aif1 |= WM8994_AIF1_BCLK_INV;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ aif1 |= WM8994_AIF1_LRCLK_INV;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ aif1 |= 0x4000;
+ wm8994_write(codec, WM8994_AIF1_CONTROL_1, aif1);
+ wm8994_write(codec, WM8994_AIF1_MASTER_SLAVE, aif2);
+ wm8994_write(codec, WM8994_AIF1_CONTROL_2, 0x4000);
+
+ return 0;
+}
+
+static int wm8994_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct wm8994_priv *wm8994 = codec->drvdata;
+ int ret, i, best, best_val, cur_val;
+ unsigned int clocking1, clocking3, aif1, aif4, aif5;
+
+ DEBUG_LOG("");
+
+ clocking1 = wm8994_read(codec, WM8994_AIF1_BCLK);
+ clocking1 &= ~WM8994_AIF1_BCLK_DIV_MASK;
+
+ clocking3 = wm8994_read(codec, WM8994_AIF1_RATE);
+ clocking3 &= ~(WM8994_AIF1_SR_MASK | WM8994_AIF1CLK_RATE_MASK);
+
+ aif1 = wm8994_read(codec, WM8994_AIF1_CONTROL_1);
+ aif1 &= ~WM8994_AIF1_WL_MASK;
+ aif4 = wm8994_read(codec, WM8994_AIF1ADC_LRCLK);
+ aif4 &= ~WM8994_AIF1ADC_LRCLK_DIR;
+ aif5 = wm8994_read(codec, WM8994_AIF1DAC_LRCLK);
+ aif5 &= ~WM8994_AIF1DAC_LRCLK_DIR_MASK;
+
+ wm8994->fs = params_rate(params);
+ wm8994->bclk = 2 * wm8994->fs;
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ wm8994->bclk *= 16;
+ break;
+
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ wm8994->bclk *= 20;
+ aif1 |= (0x01 << WM8994_AIF1_WL_SHIFT);
+ break;
+
+ case SNDRV_PCM_FORMAT_S24_LE:
+ wm8994->bclk *= 24;
+ aif1 |= (0x10 << WM8994_AIF1_WL_SHIFT);
+ break;
+
+ case SNDRV_PCM_FORMAT_S32_LE:
+ wm8994->bclk *= 32;
+ aif1 |= (0x11 << WM8994_AIF1_WL_SHIFT);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ ret = configure_clock(codec);
+ if (ret != 0)
+ return ret;
+
+ dev_dbg(codec->dev, "Target BCLK is %dHz\n", wm8994->bclk);
+
+ /* Select nearest CLK_SYS_RATE */
+ if (wm8994->fs == 8000)
+ best = 3;
+ else {
+ best = 0;
+ best_val = abs((wm8994->sysclk_rate / clk_sys_rates[0].ratio)
+ - wm8994->fs);
+
+ for (i = 1; i < ARRAY_SIZE(clk_sys_rates); i++) {
+ cur_val = abs((wm8994->sysclk_rate /
+ clk_sys_rates[i].ratio) - wm8994->fs);
+
+ if (cur_val < best_val) {
+ best = i;
+ best_val = cur_val;
+ }
+ }
+ dev_dbg(codec->dev, "Selected CLK_SYS_RATIO of %d\n",
+ clk_sys_rates[best].ratio);
+ }
+
+ clocking3 |= (clk_sys_rates[best].clk_sys_rate
+ << WM8994_AIF1CLK_RATE_SHIFT);
+
+ /* Sampling rate */
+ best = 0;
+ best_val = abs(wm8994->fs - sample_rates[0].rate);
+ for (i = 1; i < ARRAY_SIZE(sample_rates); i++) {
+ cur_val = abs(wm8994->fs - sample_rates[i].rate);
+ if (cur_val < best_val) {
+ best = i;
+ best_val = cur_val;
+ }
+ }
+ dev_dbg(codec->dev, "Selected SAMPLE_RATE of %dHz\n",
+ sample_rates[best].rate);
+
+ clocking3 |= (sample_rates[best].sample_rate << WM8994_AIF1_SR_SHIFT);
+
+ /* BCLK_DIV */
+ best = 0;
+ best_val = INT_MAX;
+ for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
+ cur_val = ((wm8994->sysclk_rate) / bclk_divs[i].div)
+ - wm8994->bclk;
+ if (cur_val < 0)
+ break;
+ if (cur_val < best_val) {
+ best = i;
+ best_val = cur_val;
+ }
+ }
+ wm8994->bclk = (wm8994->sysclk_rate) / bclk_divs[best].div;
+
+ dev_dbg(codec->dev, "Selected BCLK_DIV of %d for %dHz BCLK\n",
+ bclk_divs[best].div, wm8994->bclk);
+
+ clocking1 |= bclk_divs[best].bclk_div << WM8994_AIF1_BCLK_DIV_SHIFT;
+
+ /* LRCLK is a simple fraction of BCLK */
+ dev_dbg(codec->dev, "LRCLK_RATE is %d\n", wm8994->bclk / wm8994->fs);
+
+ aif4 |= wm8994->bclk / wm8994->fs;
+ aif5 |= wm8994->bclk / wm8994->fs;
+
+#ifdef HDMI_USE_AUDIO
+ /* set bclk to 32fs for 44.1kHz 16 bit playback.*/
+ if (wm8994->fs == 44100)
+ wm8994_write(codec, WM8994_AIF1_BCLK, 0x70);
+#endif
+
+ wm8994_write(codec, WM8994_AIF1_RATE, clocking3);
+ wm8994_write(codec, WM8994_AIF1_CONTROL_1, aif1);
+
+ return 0;
+}
+
+static int wm8994_digital_mute(struct snd_soc_dai *codec_dai, int mute)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ int mute_reg;
+ int reg;
+
+ switch (codec_dai->id) {
+ case 1:
+ mute_reg = WM8994_AIF1_DAC1_FILTERS_1;
+ break;
+ case 2:
+ mute_reg = WM8994_AIF2_DAC_FILTERS_1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (mute)
+ reg = WM8994_AIF1DAC1_MUTE;
+ else
+ reg = 0;
+
+ snd_soc_update_bits(codec, mute_reg, WM8994_AIF1DAC1_MUTE, reg);
+
+ return 0;
+}
+
+static int wm8994_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *codec_dai)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct wm8994_priv *wm8994 = codec->drvdata;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ wm8994->play_en_dis = 1;
+ else
+ wm8994->rec_en_dis = 1;
+
+ if (wm8994->power_state == CODEC_OFF) {
+ wm8994->power_state = CODEC_ON;
+ DEBUG_LOG("Turn on codec!! Power state =[%d]",
+ wm8994->power_state);
+
+ /* For initialize codec */
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1,
+ 0x3 << WM8994_VMID_SEL_SHIFT | WM8994_BIAS_ENA);
+ msleep(30);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1,
+ WM8994_VMID_SEL_NORMAL | WM8994_BIAS_ENA);
+ wm8994_write(codec, WM8994_OVERSAMPLING, 0x0000);
+ } else
+ DEBUG_LOG("Already turned on codec!!");
+
+ return 0;
+}
+
+static void wm8994_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *codec_dai)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct wm8994_priv *wm8994 = codec->drvdata;
+
+ DEBUG_LOG("%s.., wm8994->call_state = %d, current path = %d",
+ __func__, wm8994->call_state, wm8994->cur_path);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ wm8994->play_en_dis = 0;
+ DEBUG_LOG("..inside..%s..for PLAYBACK_STREAM!!", __func__);
+ if (wm8994->cur_path != OFF)
+ wm8994->cur_path = OFF;
+ } else {
+ wm8994->rec_en_dis = 0;
+ DEBUG_LOG("..inside..%s..for CAPTURE_STREAM!!", __func__);
+ if (wm8994->mic_state == MIC_NO_USE && \
+ wm8994->rec_path != MIC_OFF)
+ wm8994->rec_path = MIC_OFF;
+ }
+
+ if (wm8994->call_state == DISCONNECT) {
+ if (!wm8994->play_en_dis && !wm8994->rec_en_dis) {
+ DEBUG_LOG("Turn off Codec!!");
+ gpio_set_value(wm8994->pdata->micbias, 0);
+ wm8994->power_state = CODEC_OFF;
+ wm8994_write(codec, WM8994_SOFTWARE_RESET, 0x0000);
+ return;
+ }
+ }
+
+ DEBUG_LOG("Preserve codec state for call[%d].",
+ wm8994->call_state);
+
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ wm8994->universal_mic_path[MIC_OFF] (codec);
+ } else {
+ if (wm8994->call_state == CONNECT) {
+ int val;
+ val = wm8994_read(codec, WM8994_AIF1_DAC1_FILTERS_1);
+ val &= ~(WM8994_AIF1DAC1_MUTE_MASK);
+ val |= (WM8994_AIF1DAC1_MUTE);
+ wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, val);
+ }
+ }
+
+ DEBUG_LOG("exiting ...%s...", __func__);
+
+}
+
+static struct snd_soc_device *wm8994_socdev;
+static struct snd_soc_codec *wm8994_codec;
+
+#define WM8994_RATES SNDRV_PCM_RATE_8000_96000
+#define WM8994_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+static struct snd_soc_dai_ops wm8994_ops = {
+ .startup = wm8994_startup,
+ .shutdown = wm8994_shutdown,
+ .set_sysclk = wm8994_set_sysclk,
+ .set_fmt = wm8994_set_dai_fmt,
+ .hw_params = wm8994_hw_params,
+ .digital_mute = NULL,
+};
+
+struct snd_soc_dai wm8994_dai = {
+
+ .name = "WM8994 PAIFRX",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 6,
+ .rates = WM8994_RATES,
+ .formats = WM8994_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = WM8994_RATES,
+ .formats = WM8994_FORMATS,
+ },
+
+ .ops = &wm8994_ops,
+};
+
+/*
+ * initialise the WM8994 driver
+ * register the mixer and dsp interfaces with the kernel
+ */
+static int wm8994_init(struct wm8994_priv *wm8994_private)
+{
+ struct snd_soc_codec *codec = &wm8994_private->codec;
+ struct wm8994_priv *wm8994;
+ int ret = 0;
+ DEBUG_LOG("");
+ codec->drvdata = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL);
+ if (codec->drvdata == NULL)
+ return -ENOMEM;
+
+ wm8994 = codec->drvdata;
+
+ mutex_init(&codec->mutex);
+ INIT_LIST_HEAD(&codec->dapm_widgets);
+ INIT_LIST_HEAD(&codec->dapm_paths);
+ codec->name = "WM8994";
+ codec->owner = THIS_MODULE;
+ codec->read = wm8994_read;
+ codec->write = wm8994_write;
+ codec->set_bias_level = NULL;
+ codec->dai = &wm8994_dai;
+ codec->num_dai = 1;
+ wm8994->universal_playback_path = universal_wm8994_playback_paths;
+ wm8994->universal_voicecall_path = universal_wm8994_voicecall_paths;
+ wm8994->universal_mic_path = universal_wm8994_mic_paths;
+ wm8994->universal_clock_control = universal_clock_controls;
+ wm8994->cur_path = OFF;
+ wm8994->rec_path = MIC_OFF;
+ wm8994->call_state = DISCONNECT;
+ wm8994->power_state = CODEC_OFF;
+ wm8994->mic_state = MIC_NO_USE;
+ wm8994->play_en_dis = 0;
+ wm8994->rec_en_dis = 0;
+ wm8994->pdata = pdata;
+
+ wm8994->universal_clock_control(codec, CODEC_ON);
+
+ wm8994->codec_clk = clk_get(NULL, "usb_osc");
+
+ if (IS_ERR(wm8994->codec_clk)) {
+ pr_err("failed to get MCLK clock from AP\n");
+ goto card_err;
+ }
+
+ wm8994_write(codec, WM8994_SOFTWARE_RESET, 0x0000);
+
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1,
+ 0x3 << WM8994_VMID_SEL_SHIFT | WM8994_BIAS_ENA);
+ msleep(10);
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1,
+ WM8994_VMID_SEL_NORMAL | WM8994_BIAS_ENA);
+
+ wm8994->hw_version = wm8994_read(codec, 0x100);
+
+ wm8994_socdev->card->codec = codec;
+ wm8994_codec = codec;
+
+ ret = snd_soc_new_pcms(wm8994_socdev, SNDRV_DEFAULT_IDX1,
+ SNDRV_DEFAULT_STR1);
+ if (ret < 0) {
+ DEBUG_LOG_ERR("failed to create pcms\n");
+ goto pcm_err;
+ }
+
+ wm8994_add_controls(codec);
+ wm8994_add_widgets(codec);
+
+ return ret;
+
+card_err:
+ snd_soc_free_pcms(wm8994_socdev);
+ snd_soc_dapm_free(wm8994_socdev);
+pcm_err:
+
+ return ret;
+}
+
+/* If the i2c layer weren't so broken, we could pass this kind of data
+ around */
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+
+
+static void *control_data1;
+
+static int wm8994_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct snd_soc_codec *codec;
+ struct wm8994_priv *wm8994_priv;
+ int ret;
+
+ DEBUG_LOG("");
+
+ wm8994_priv = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL);
+ if (wm8994_priv == NULL)
+ return -ENOMEM;
+
+ codec = &wm8994_priv->codec;
+#ifdef PM_DEBUG
+ pm_codec = codec;
+#endif
+
+ pdata = i2c->dev.platform_data;
+
+ if (!pdata)
+ dev_err(&i2c->dev, "failed to initialize WM8994\n");
+
+ /* CODEC LDO SETTING */
+ if (gpio_is_valid(pdata->ldo)) {
+ ret = gpio_request(pdata->ldo, "WM8994 LDO");
+ if (ret) {
+ pr_err("Failed to request CODEC_LDO_EN!\n");
+ goto err_ldo;
+ }
+ gpio_direction_output(pdata->ldo, 0);
+ }
+
+ s3c_gpio_setpull(pdata->ldo, S3C_GPIO_PULL_NONE);
+
+ /* For preserving output of codec related pins */
+ s3c_gpio_slp_cfgpin(pdata->ldo, S3C_GPIO_SLP_PREV);
+ s3c_gpio_slp_setpull_updown(pdata->ldo, S3C_GPIO_PULL_NONE);
+
+ /* EAR_SEL SETTING(only crespo HW) */
+ if (gpio_is_valid(pdata->ear_sel)) {
+ ret = gpio_request(pdata->ear_sel, "EAR SEL");
+ if (ret) {
+ pr_err("Failed to request EAR_SEL!\n");
+ goto err_earsel;
+ }
+ gpio_direction_output(pdata->ear_sel, 0);
+ }
+ s3c_gpio_setpull(pdata->ear_sel, S3C_GPIO_PULL_NONE);
+
+ s3c_gpio_slp_cfgpin(pdata->ear_sel, S3C_GPIO_SLP_PREV);
+ s3c_gpio_slp_setpull_updown(pdata->ear_sel, S3C_GPIO_PULL_NONE);
+
+ if (gpio_is_valid(pdata->micbias)) {
+ ret = gpio_request(pdata->micbias, "MICBIAS_EN");
+ if (ret) {
+ pr_err("Failed to request MICBIAS_EN!\n");
+ goto err_micbias;
+ }
+ gpio_direction_output(pdata->micbias, 0);
+ }
+ s3c_gpio_slp_cfgpin(pdata->micbias, S3C_GPIO_SLP_PREV);
+
+ wm8994_ldo_control(pdata, 1);
+ msleep(10);
+
+ codec->hw_write = (hw_write_t) i2c_master_send;
+ i2c_set_clientdata(i2c, wm8994_priv);
+ codec->control_data = i2c;
+ codec->dev = &i2c->dev;
+ control_data1 = i2c;
+
+ ret = wm8994_init(wm8994_priv);
+ if (ret < 0)
+ dev_err(&i2c->dev, "failed to initialize WM8994\n");
+
+ return ret;
+
+err_ldo:
+ gpio_free(pdata->ldo);
+ return ret;
+err_micbias:
+ gpio_free(pdata->micbias);
+ return ret;
+err_earsel:
+ gpio_free(pdata->ear_sel);
+ return ret;
+}
+
+static int wm8994_i2c_remove(struct i2c_client *client)
+{
+ struct wm8994_priv *wm8994_priv = i2c_get_clientdata(client);
+
+ gpio_free(pdata->ldo);
+ gpio_free(pdata->micbias);
+ gpio_free(pdata->ear_sel);
+
+ kfree(pdata);
+ kfree(wm8994_priv);
+ return 0;
+}
+
+static const struct i2c_device_id wm8994_i2c_id[] = {
+ {"wm8994", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id);
+
+static struct i2c_driver wm8994_i2c_driver = {
+ .driver = {
+ .name = "WM8994 I2C Codec",
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8994_i2c_probe,
+ .remove = wm8994_i2c_remove,
+ .id_table = wm8994_i2c_id,
+};
+
+static int wm8994_add_i2c_device(struct platform_device *pdev,
+ const struct wm8994_setup_data *setup)
+{
+ int ret;
+
+ ret = i2c_add_driver(&wm8994_i2c_driver);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "can't add i2c driver\n");
+ return ret;
+ }
+
+ return 0;
+
+err_driver:
+ i2c_del_driver(&wm8994_i2c_driver);
+ return -ENODEV;
+}
+#endif
+
+static int wm8994_probe(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct wm8994_setup_data *setup;
+
+ int ret = 0;
+
+ pr_info("WM8994 Audio Codec %s\n", WM8994_VERSION);
+
+ setup = socdev->codec_data;
+ wm8994_socdev = socdev;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ if (setup->i2c_address)
+ ret = wm8994_add_i2c_device(pdev, setup);
+#else
+ /* Add other interfaces here */
+#endif
+ return ret;
+}
+
+/* power down chip */
+static int wm8994_remove(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec = wm8994_codec;
+
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ i2c_unregister_device(codec->control_data);
+ i2c_del_driver(&wm8994_i2c_driver);
+#endif
+
+ kfree(codec->drvdata);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int wm8994_suspend(struct platform_device *pdev, pm_message_t msg)
+{
+ struct snd_soc_codec *codec = wm8994_codec;
+ struct wm8994_priv *wm8994 = codec->drvdata;
+
+ DEBUG_LOG("%s..", __func__);
+
+ if (wm8994->call_state == DISCONNECT && wm8994->cur_path == OFF) {
+ wm8994->power_state = OFF;
+ wm8994_write(codec, WM8994_SOFTWARE_RESET, 0x0000);
+ wm8994_ldo_control(wm8994->pdata, 0);
+ wm8994->universal_clock_control(codec, CODEC_OFF);
+ }
+
+ return 0;
+}
+
+static int wm8994_resume(struct platform_device *pdev)
+{
+ struct snd_soc_codec *codec = wm8994_codec;
+ struct wm8994_priv *wm8994 = codec->drvdata;
+
+ DEBUG_LOG("%s..", __func__);
+ DEBUG_LOG_ERR("------WM8994 Revision = [%d]-------",
+ wm8994->hw_version);
+
+ if (wm8994->call_state == DISCONNECT && wm8994->cur_path == OFF) {
+ /* Turn on sequence by recommend Wolfson.*/
+ wm8994_ldo_control(wm8994->pdata, 1);
+ wm8994->universal_clock_control(codec, CODEC_ON);
+ wm8994->power_state = CODEC_ON;
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1,
+ 0x3 << WM8994_VMID_SEL_SHIFT | WM8994_BIAS_ENA);
+ msleep(50); /* Wait VMID up */
+ wm8994_write(codec, WM8994_POWER_MANAGEMENT_1,
+ WM8994_VMID_SEL_NORMAL | WM8994_BIAS_ENA);
+
+ wm8994_write(codec, WM8994_OVERSAMPLING, 0x0000);
+ }
+ return 0;
+}
+#endif
+
+struct snd_soc_codec_device soc_codec_dev_wm8994 = {
+ .probe = wm8994_probe,
+ .remove = wm8994_remove,
+#ifdef CONFIG_PM
+ .suspend = wm8994_suspend,
+ .resume = wm8994_resume,
+#endif
+};
+
+static int __init wm8994_modinit(void)
+{
+ int ret;
+ ret = snd_soc_register_dai(&wm8994_dai);
+ if (ret)
+ pr_err("..dai registration failed..\n");
+
+ return ret;
+}
+
+module_init(wm8994_modinit);
+
+static void __exit wm8994_exit(void)
+{
+ snd_soc_unregister_dai(&wm8994_dai);
+}
+
+module_exit(wm8994_exit);
+
+MODULE_DESCRIPTION("ASoC WM8994 driver");
+MODULE_AUTHOR("Shaju Abraham shaju.abraham@samsung.com");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8994_samsung.h b/sound/soc/codecs/wm8994_samsung.h
new file mode 100755
index 0000000..5c285de
--- /dev/null
+++ b/sound/soc/codecs/wm8994_samsung.h
@@ -0,0 +1,119 @@
+/*
+ * wm8994_samsung.h -- WM8994 Soc Audio driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _WM8994_SAMSUNG_H
+#define _WM8994_SAMSUNG_H
+
+#include <sound/soc.h>
+#include <linux/mfd/wm8994/wm8994_pdata.h>
+
+extern struct snd_soc_codec_device soc_codec_dev_wm8994;
+
+/* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */
+#define WM8994_SYSCLK_MCLK1 1
+#define WM8994_SYSCLK_MCLK2 2
+#define WM8994_SYSCLK_FLL1 3
+#define WM8994_SYSCLK_FLL2 4
+
+#define WM8994_FLL1 1
+#define WM8994_FLL2 2
+
+/* Added belows codes by Samsung Electronics.*/
+
+#include "wm8994_def.h"
+
+extern struct snd_soc_dai wm8994_dai;
+
+#define WM8994_SYSCLK_MCLK 1
+#define WM8994_SYSCLK_FLL 2
+
+#define AUDIO_COMMON_DEBUG 0
+
+/*
+ * Definitions of enum type
+ */
+enum audio_path {
+ OFF, RCV, SPK, HP, BT, SPK_HP,
+ RING_SPK, RING_HP, RING_SPK_HP
+};
+enum mic_path { MAIN, SUB, BT_REC, MIC_OFF};
+enum call_state { DISCONNECT, CONNECT};
+enum power_state { CODEC_OFF, CODEC_ON };
+enum mic_state { MIC_NO_USE, MIC_USE};
+enum ringtone_state { DEACTIVE, ACTIVE};
+enum recognition {REC_OFF, REC_ON};
+
+typedef void (*select_route)(struct snd_soc_codec *);
+typedef void (*select_mic_route)(struct snd_soc_codec *);
+typedef int (*select_clock_control)(struct snd_soc_codec *, int);
+
+
+struct wm8994_setup_data {
+ int i2c_bus;
+ unsigned short i2c_address;
+};
+
+struct wm8994_priv {
+ struct snd_soc_codec codec;
+ int master;
+ int sysclk_source;
+ unsigned int mclk_rate;
+ unsigned int sysclk_rate;
+ unsigned int fs;
+ unsigned int bclk;
+ unsigned int hw_version;
+ enum audio_path cur_path;
+ enum mic_path rec_path;
+ enum call_state call_state;
+ enum power_state power_state;
+ enum mic_state mic_state;
+ enum recognition recognition_active;
+ enum ringtone_state ringtone_active;
+ select_route *universal_playback_path;
+ select_route *universal_voicecall_path;
+ select_mic_route *universal_mic_path;
+ select_clock_control universal_clock_control;
+ bool play_en_dis;
+ bool rec_en_dis;
+ struct wm8994_platform_data *pdata;
+ struct clk *codec_clk;
+};
+
+#if AUDIO_COMMON_DEBUG
+#define DEBUG_LOG(format, ...)\
+ printk(KERN_INFO "[ "SUBJECT " (%s,%d) ] " format "\n", \
+ __func__, __LINE__, ## __VA_ARGS__);
+#else
+#define DEBUG_LOG(format, ...)
+#endif
+
+#define DEBUG_LOG_ERR(format, ...)\
+ printk(KERN_ERR "[ "SUBJECT " (%s,%d) ] " format "\n", \
+ __func__, __LINE__, ## __VA_ARGS__);
+
+/* Definitions of function prototype. */
+inline unsigned int wm8994_read(struct snd_soc_codec *codec, unsigned int reg);
+int wm8994_write(struct snd_soc_codec *codec,
+ unsigned int reg, unsigned int value);
+int wm8994_configure_clock(struct snd_soc_codec *codec, int en);
+void wm8994_disable_playback_path(struct snd_soc_codec *codec,
+ enum audio_path path);
+void wm8994_disable_rec_path(struct snd_soc_codec *codec);
+void wm8994_record_main_mic(struct snd_soc_codec *codec);
+void wm8994_record_headset_mic(struct snd_soc_codec *codec);
+void wm8994_record_bluetooth(struct snd_soc_codec *codec);
+void wm8994_set_playback_receiver(struct snd_soc_codec *codec);
+void wm8994_set_playback_headset(struct snd_soc_codec *codec);
+void wm8994_set_playback_speaker(struct snd_soc_codec *codec);
+void wm8994_set_playback_speaker_headset(struct snd_soc_codec *codec);
+void wm8994_set_voicecall_common_setting(struct snd_soc_codec *codec);
+void wm8994_set_voicecall_receiver(struct snd_soc_codec *codec);
+void wm8994_set_voicecall_headset(struct snd_soc_codec *codec);
+void wm8994_set_voicecall_speaker(struct snd_soc_codec *codec);
+void wm8994_set_voicecall_bluetooth(struct snd_soc_codec *codec);
+#endif
diff --git a/sound/soc/samsung/herring-wm8994.c b/sound/soc/samsung/herring-wm8994.c
index ca33b46..d19e2ef 100644
--- a/sound/soc/samsung/herring-wm8994.c
+++ b/sound/soc/samsung/herring-wm8994.c
@@ -18,7 +18,7 @@
#include <sound/soc-dapm.h>
#include <mach/regs-clock.h>
#include <plat/regs-iis.h>
-#include "../codecs/wm8994.h"
+#include "../codecs/wm8994_samsung.h"
#include "s3c-dma.h"
#include "s5pc1xx-i2s.h"
#include "s3c-i2s-v2.h"