aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r--sound/soc/codecs/Kconfig.voodoo8
-rw-r--r--sound/soc/codecs/wm8994_voodoo.c201
-rw-r--r--sound/soc/codecs/wm8994_voodoo.h37
3 files changed, 177 insertions, 69 deletions
diff --git a/sound/soc/codecs/Kconfig.voodoo b/sound/soc/codecs/Kconfig.voodoo
index 5f85148..dfb3250 100644
--- a/sound/soc/codecs/Kconfig.voodoo
+++ b/sound/soc/codecs/Kconfig.voodoo
@@ -37,14 +37,12 @@ config SND_VOODOO_RECORD_PRESETS
- Loud environment - concert
config SND_VOODOO_FM
- bool "FM radio: restore a normal frequency response"
- depends on SND_VOODOO && SND_ARIES_SOC_WM8994
- default n if S5PC110_T959_BOARD=y || S5PC110_KEPLER_BOARD=y || S5PV210_VICTORY=y || M110S=y
- default y
+ bool "FM radio: frequency response and levels optimizations"
+ depends on SND_VOODOO && ARIES_EUR
+ default n
help
Adds a control to enable or disable the high-pass filter on FM radio
-
config SND_VOODOO_MODULE
tristate "Build also as module (incomplete)"
depends on SND_VOODOO && m
diff --git a/sound/soc/codecs/wm8994_voodoo.c b/sound/soc/codecs/wm8994_voodoo.c
index 82709d4..b10dd0b 100644
--- a/sound/soc/codecs/wm8994_voodoo.c
+++ b/sound/soc/codecs/wm8994_voodoo.c
@@ -13,16 +13,17 @@
#include <sound/soc.h>
#include <linux/delay.h>
#include <linux/miscdevice.h>
+#include <linux/version.h>
#include "wm8994_voodoo.h"
#ifndef MODULE
-#ifdef NEXUS_S
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
#include "wm8994_samsung.h"
#else
#include "wm8994.h"
#endif
#else
-#ifdef NEXUS_S
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
#include "../wm8994_samsung.h"
#else
#include "../wm8994.h"
@@ -30,7 +31,7 @@
#endif
#define SUBJECT "wm8994_voodoo.c"
-#define VOODOO_SOUND_VERSION 7
+#define VOODOO_SOUND_VERSION 8
#ifdef MODULE
#include "tegrak_voodoo_sound.h"
@@ -103,7 +104,7 @@ static ssize_t name##_store(struct device *dev, struct device_attribute *attr, \
return size; \
}
-#ifdef NEXUS_S
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
#define DECLARE_WM8994(codec) struct wm8994_priv *wm8994 = codec->drvdata;
#else
#define DECLARE_WM8994(codec) struct wm8994_priv *wm8994 = codec->private_data;
@@ -113,13 +114,15 @@ static ssize_t name##_store(struct device *dev, struct device_attribute *attr, \
void update_hpvol()
{
unsigned short val;
+ DECLARE_WM8994(codec);
+
+ // don't affect headphone amplifier volume
+ // when not on heapdhones or if call is active
+ if (!is_path(HEADPHONES)
+ || (wm8994->codec_state & CALL_ACTIVE))
+ return;
bypass_write_hook = true;
- // hard limit to 62 because 63 introduces distortions
- if (hplvol > 62)
- hplvol = 62;
- if (hprvol > 62)
- hprvol = 62;
// we don't need the Volume Update flag when sending the first volume
val = (WM8994_HPOUT1L_MUTE_N | hplvol);
@@ -147,7 +150,11 @@ void update_fm_radio_headset_restore_freqs(bool with_mute)
return;
if (with_mute) {
- wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1, 0x236);
+ wm8994_write(codec, WM8994_AIF2_DAC_FILTERS_1,
+ WM8994_AIF2DAC_MUTE |
+ WM8994_AIF2DAC_MUTERATE |
+ WM8994_AIF2DAC_UNMUTE_RAMP |
+ WM8994_AIF2DAC_DEEMP_MASK);
msleep(180);
}
@@ -157,7 +164,9 @@ void update_fm_radio_headset_restore_freqs(bool with_mute)
wm8994_write(codec, WM8994_SIDETONE, 0x0000);
// disable 4FS ultrasonic mode and
// restore the hi-fi <4Hz hi pass filter
- wm8994_write(codec, WM8994_AIF2_ADC_FILTERS, 0x1800);
+ wm8994_write(codec, WM8994_AIF2_ADC_FILTERS,
+ WM8994_AIF2ADCL_HPF |
+ WM8994_AIF2ADCR_HPF);
} else {
// default settings in GT-I9000 Froyo XXJPX kernel sources
wm8994_write(codec, WM8994_SIDETONE, 0x01c0);
@@ -234,11 +243,17 @@ void update_recording_preset(bool with_mute)
// High sensitivy:
// Original - 4.5 dB, IN1L_VOL1=10101 (+15 dB)
wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME, 0x0115);
- wm8994_write(codec, WM8994_INPUT_MIXER_3, 0x30);
+ wm8994_write(codec, WM8994_INPUT_MIXER_3,
+ WM8994_IN1L_TO_MIXINL |
+ WM8994_IN1L_MIXINL_VOL);
// DRC Input: -6dB, Ouptut -3.75dB
// Above knee 1/8, Below knee 1/2
// Max gain 24 / Min gain -12
- wm8994_write(codec, WM8994_AIF1_DRC1_1, 0x009A);
+ wm8994_write(codec, WM8994_AIF1_DRC1_1,
+ WM8994_AIF1DRC1_SIG_DET_MODE |
+ WM8994_AIF1DRC1_QR |
+ WM8994_AIF1DRC1_ANTICLIP |
+ WM8994_AIF1ADC1L_DRC_ENA);
wm8994_write(codec, WM8994_AIF1_DRC1_2, 0x0426);
wm8994_write(codec, WM8994_AIF1_DRC1_3, 0x0019);
wm8994_write(codec, WM8994_AIF1_DRC1_4, 0x0105);
@@ -247,11 +262,16 @@ void update_recording_preset(bool with_mute)
// Concert new: IN1L_VOL1=10110 (+4.5 dB)
// +30dB input mixer gain deactivated
wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME, 0x010F);
- wm8994_write(codec, WM8994_INPUT_MIXER_3, 0x20);
+ wm8994_write(codec, WM8994_INPUT_MIXER_3,
+ WM8994_IN1L_TO_MIXINL);
// DRC Input: -4.5dB, Ouptut -6.75dB
// Above knee 1/4, Below knee 1/2
// Max gain 24 / Min gain -12
- wm8994_write(codec, WM8994_AIF1_DRC1_1, 0x009A);
+ wm8994_write(codec, WM8994_AIF1_DRC1_1,
+ WM8994_AIF1DRC1_SIG_DET_MODE |
+ WM8994_AIF1DRC1_QR |
+ WM8994_AIF1DRC1_ANTICLIP |
+ WM8994_AIF1ADC1L_DRC_ENA);
wm8994_write(codec, WM8994_AIF1_DRC1_2, 0x0846);
wm8994_write(codec, WM8994_AIF1_DRC1_3, 0x0011);
wm8994_write(codec, WM8994_AIF1_DRC1_4, 0x00C9);
@@ -261,11 +281,16 @@ void update_recording_preset(bool with_mute)
// Original - 36 dB - 30 dB IN1L_VOL1=00000 (-16.5 dB)
// +30dB input mixer gain deactivated
wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME, 0x0100);
- wm8994_write(codec, WM8994_INPUT_MIXER_3, 0x20);
+ wm8994_write(codec, WM8994_INPUT_MIXER_3,
+ WM8994_IN1L_TO_MIXINL);
// DRC Input: -7.5dB, Ouptut -6dB
// Above knee 1/8, Below knee 1/4
// Max gain 36 / Min gain -12
- wm8994_write(codec, WM8994_AIF1_DRC1_1, 0x009A);
+ wm8994_write(codec, WM8994_AIF1_DRC1_1,
+ WM8994_AIF1DRC1_SIG_DET_MODE |
+ WM8994_AIF1DRC1_QR |
+ WM8994_AIF1DRC1_ANTICLIP |
+ WM8994_AIF1ADC1L_DRC_ENA);
wm8994_write(codec, WM8994_AIF1_DRC1_2, 0x0847);
wm8994_write(codec, WM8994_AIF1_DRC1_3, 0x001A);
wm8994_write(codec, WM8994_AIF1_DRC1_4, 0x00C9);
@@ -277,11 +302,16 @@ void update_recording_preset(bool with_mute)
// IN1L_VOL1=01101 (+27 dB)
// +30dB input mixer gain deactivated
wm8994_write(codec, WM8994_LEFT_LINE_INPUT_1_2_VOLUME, 0x055D);
- wm8994_write(codec, WM8994_INPUT_MIXER_3, 0x20);
+ wm8994_write(codec, WM8994_INPUT_MIXER_3,
+ WM8994_IN1L_TO_MIXINL);
// DRC Input: -18.5dB, Ouptut -9dB
// Above knee 1/8, Below knee 1/2
// Max gain 18 / Min gain -12
- wm8994_write(codec, WM8994_AIF1_DRC1_1, 0x009A);
+ wm8994_write(codec, WM8994_AIF1_DRC1_1,
+ WM8994_AIF1DRC1_SIG_DET_MODE |
+ WM8994_AIF1DRC1_QR |
+ WM8994_AIF1DRC1_ANTICLIP |
+ WM8994_AIF1ADC1L_DRC_ENA);
wm8994_write(codec, WM8994_AIF1_DRC1_2, 0x0845);
wm8994_write(codec, WM8994_AIF1_DRC1_3, 0x0019);
wm8994_write(codec, WM8994_AIF1_DRC1_4, 0x030C);
@@ -303,14 +333,20 @@ bool is_path(int unified_path)
|| wm8994->fmradio_path == FMR_SPK
|| wm8994->fmradio_path == FMR_SPK_MIX);
#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+ return (wm8994->cur_path == SPK
+ || wm8994->cur_path == SPK_HP);
+#else
return (wm8994->cur_path == SPK
|| wm8994->cur_path == RING_SPK);
#endif
+#endif
// headphones
// FIXME: be sure dac_direct doesn't break phone calls on TAB
// with these spath detection settings (HP4P)
case HEADPHONES:
+
#ifdef NEXUS_S
return (wm8994->cur_path == HP
|| wm8994->cur_path == HP_NO_MIC);
@@ -323,11 +359,17 @@ bool is_path(int unified_path)
#ifdef M110S
return (wm8994->cur_path == HP);
#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+ return (wm8994->cur_path == HP
+ || wm8994->cur_path == HP_NO_MIC
+ || wm8994->fmradio_path == FMR_HP);
+#else
return (wm8994->cur_path == HP
|| wm8994->fmradio_path == FMR_HP);
#endif
#endif
#endif
+#endif
// FM Radio on headphones
case RADIO_HEADPHONES:
@@ -366,7 +408,6 @@ void update_speaker_tuning(bool with_mute)
if (!(is_path(SPEAKER) || (wm8994->codec_state & CALL_ACTIVE)))
return;
- printk("We are on speaker!\n");
if (speaker_tuning) {
// DRC settings
wm8994_write(codec, WM8994_AIF1_DRC1_3, 0x0010);
@@ -465,15 +506,18 @@ void update_fll_tuning(bool with_mute)
bypass_write_hook = false;
}
-unsigned short mono_downmix_get_value(unsigned short val)
+unsigned short mono_downmix_get_value(unsigned short val, bool can_reverse)
{
- // depends on the output path in order to preserve mono downmixing
- // on speaker
- if (!is_path(SPEAKER)) {
- if (mono_downmix)
+ DECLARE_WM8994(codec);
+
+ // Takes care not switching to Stereo on speaker or during a call
+ if (!is_path(SPEAKER) && !(wm8994->codec_state & CALL_ACTIVE)) {
+ if (mono_downmix) {
val |= WM8994_AIF1DAC1_MONO;
- else
- val &= ~WM8994_AIF1DAC1_MONO;
+ } else {
+ if (can_reverse)
+ val &= ~WM8994_AIF1DAC1_MONO;
+ }
}
return val;
@@ -483,11 +527,14 @@ void update_mono_downmix(bool with_mute)
{
unsigned short val1, val2, val3;
val1 = mono_downmix_get_value(wm8994_read
- (codec, WM8994_AIF1_DAC1_FILTERS_1));
+ (codec, WM8994_AIF1_DAC1_FILTERS_1),
+ true);
val2 = mono_downmix_get_value(wm8994_read
- (codec, WM8994_AIF1_DAC2_FILTERS_1));
+ (codec, WM8994_AIF1_DAC2_FILTERS_1),
+ true);
val3 = mono_downmix_get_value(wm8994_read
- (codec, WM8994_AIF2_DAC_FILTERS_1));
+ (codec, WM8994_AIF2_DAC_FILTERS_1),
+ true);
bypass_write_hook = true;
wm8994_write(codec, WM8994_AIF1_DAC1_FILTERS_1, val1);
@@ -496,19 +543,22 @@ void update_mono_downmix(bool with_mute)
bypass_write_hook = false;
}
-unsigned short dac_direct_get_value(unsigned short val)
+unsigned short dac_direct_get_value(unsigned short val, bool can_reverse)
{
DECLARE_WM8994(codec);
- if (is_path(HEADPHONES)
- && (wm8994->codec_state & PLAYBACK_ACTIVE)
- && !(wm8994->codec_state & CALL_ACTIVE)
- && !(wm8994->stream_state & PCM_STREAM_PLAYBACK)) {
+ if ((is_path(HEADPHONES)
+ && (wm8994->codec_state & PLAYBACK_ACTIVE)
+ && (wm8994->stream_state & PCM_STREAM_PLAYBACK)
+ && !(wm8994->codec_state & CALL_ACTIVE))
+ || is_path(RADIO_HEADPHONES)) {
if (dac_direct) {
if (val == WM8994_DAC1L_TO_MIXOUTL)
return WM8994_DAC1L_TO_HPOUT1L;
- else if (val == WM8994_DAC1L_TO_HPOUT1L)
+ } else {
+ if (val == WM8994_DAC1L_TO_HPOUT1L
+ && can_reverse)
return WM8994_DAC1L_TO_MIXOUTL;
}
}
@@ -519,8 +569,10 @@ unsigned short dac_direct_get_value(unsigned short val)
void update_dac_direct(bool with_mute)
{
unsigned short val1, val2;
- val1 = dac_direct_get_value(wm8994_read(codec, WM8994_OUTPUT_MIXER_1));
- val2 = dac_direct_get_value(wm8994_read(codec, WM8994_OUTPUT_MIXER_2));
+ val1 = dac_direct_get_value(wm8994_read(codec,
+ WM8994_OUTPUT_MIXER_1), true);
+ val2 = dac_direct_get_value(wm8994_read(codec,
+ WM8994_OUTPUT_MIXER_2), true);
bypass_write_hook = true;
wm8994_write(codec, WM8994_OUTPUT_MIXER_1, val1);
@@ -550,6 +602,12 @@ static ssize_t headphone_amplifier_level_store(struct device *dev,
if (sscanf(buf, "%hu", &vol) == 1) {
// left and right are set to the same volumes
hplvol = hprvol = vol;
+ // hard limit to 62 because 63 introduces distortions
+ if (hplvol > 62)
+ hplvol = 62;
+ if (hprvol > 62)
+ hprvol = 62;
+
update_hpvol();
}
return size;
@@ -820,6 +878,12 @@ static DEVICE_ATTR(enable, S_IRUGO | S_IWUGO,
enable_store);
#endif
+#ifdef MODULE
+static DEVICE_ATTR(module, 0,
+ NULL,
+ NULL);
+#endif
+
static struct attribute *voodoo_sound_attributes[] = {
#ifdef CONFIG_SND_VOODOO_HP_LEVEL_CONTROL
&dev_attr_headphone_amplifier_level.attr,
@@ -844,6 +908,9 @@ static struct attribute *voodoo_sound_attributes[] = {
&dev_attr_wm8994_register_dump.attr,
&dev_attr_wm8994_write.attr,
#endif
+#ifdef MODULE
+ &dev_attr_module.attr,
+#endif
&dev_attr_version.attr,
NULL
};
@@ -941,18 +1008,18 @@ void voodoo_hook_record_main_mic()
}
#endif
+#ifdef NEXUS_S
void voodoo_hook_playback_speaker()
{
// global kill switch
if (!enable)
return;
-#ifdef NEXUS_S
if (!speaker_tuning)
return;
update_speaker_tuning(false);
-#endif
}
+#endif
unsigned int voodoo_hook_wm8994_write(struct snd_soc_codec *codec_,
unsigned int reg, unsigned int value)
@@ -988,6 +1055,15 @@ unsigned int voodoo_hook_wm8994_write(struct snd_soc_codec *codec_,
#endif
#ifdef CONFIG_SND_VOODOO_FM
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+ // FM tuning virtual hook for Gingerbread
+ if (is_path(RADIO_HEADPHONES)) {
+ if (reg == WM8994_AIF2_DRC_1
+ || reg == WM8994_AIF2_DAC_FILTERS_1)
+ voodoo_hook_fmradio_headset();
+ }
+#else
+ // FM tuning virtual hook for Froyo
if (is_path(RADIO_HEADPHONES)) {
if (reg == WM8994_INPUT_MIXER_2
|| reg == WM8994_AIF2_DRC_1
@@ -995,45 +1071,76 @@ unsigned int voodoo_hook_wm8994_write(struct snd_soc_codec *codec_,
voodoo_hook_fmradio_headset();
}
#endif
-
+#endif
+ // global Oversampling tuning
if (reg == WM8994_OVERSAMPLING)
value = osr128_get_value(value);
+ // global Anti-Jitter tuning
if (reg == WM8994_FLL1_CONTROL_4)
value = fll_tuning_get_value(value);
+ // global Mono downmix tuning
if (reg == WM8994_AIF1_DAC1_FILTERS_1
|| reg == WM8994_AIF1_DAC2_FILTERS_1
|| reg == WM8994_AIF2_DAC_FILTERS_1)
- value = mono_downmix_get_value(value);
+ value = mono_downmix_get_value(value, false);
+ // DAC direct tuning virtual hook
if (reg == WM8994_OUTPUT_MIXER_1
|| reg == WM8994_OUTPUT_MIXER_2)
- value = dac_direct_get_value(value);
+ value = dac_direct_get_value(value, false);
+
}
#ifdef CONFIG_SND_VOODOO_DEBUG_LOG
// log every write to dmesg
- printk("Voodoo sound: wm8994_write register= [%X] value= [%X]\n",
- reg, value);
#ifdef NEXUS_S
printk("Voodoo sound: codec_state=%u, stream_state=%u, "
"cur_path=%i, rec_path=%i, "
"power_state=%i\n",
wm8994->codec_state, wm8994->stream_state,
- wm8994->cur_path, wm8994->rec_path, wm8994->power_state);
+ wm8994->cur_path, wm8994->rec_path,
+ wm8994->power_state);
#else
- printk("Voodoo sound: codec_state=%u, stream_state=%u, "
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+ printk("Voodoo sound: wm8994_write 0x%03X 0x%04X "
+ "codec_state=%u, stream_state=%u, "
"cur_path=%i, rec_path=%i, "
"fmradio_path=%i, fmr_mix_path=%i, "
+ "input_source=%i, output_source=%i, "
+ "power_state=%i\n",
+ reg, value,
+ wm8994->codec_state, wm8994->stream_state,
+ wm8994->fmradio_path, wm8994->fmr_mix_path,
+ wm8994->cur_path, wm8994->rec_path,
+ wm8994->input_source, wm8994->output_source,
+ wm8994->power_state);
+#else
+ printk("Voodoo sound: wm8994_write 0x%03X 0x%04X "
+ "codec_state=%u, stream_state=%u, "
+ "cur_path=%i, rec_path=%i, "
+ "fmradio_path=%i, fmr_mix_path=%i, "
+#ifdef CONFIG_S5PC110_KEPLER_BOARD
+ "call_record_path=%i, call_record_ch=%i, "
+ "AUDIENCE_state=%i, "
+ "Fac_SUB_MIC_state=%i, TTY_state=%i, "
+#endif
"power_state=%i, "
"recognition_active=%i, ringtone_active=%i\n",
+ reg, value,
wm8994->codec_state, wm8994->stream_state,
wm8994->cur_path, wm8994->rec_path,
wm8994->fmradio_path, wm8994->fmr_mix_path,
+#ifdef CONFIG_S5PC110_KEPLER_BOARD
+ wm8994->call_record_path, wm8994->call_record_ch,
+ wm8994->AUDIENCE_state,
+ wm8994->Fac_SUB_MIC_state, wm8994->TTY_state,
+#endif
wm8994->power_state,
wm8994->recognition_active, wm8994->ringtone_active);
#endif
#endif
+#endif
return value;
}
diff --git a/sound/soc/codecs/wm8994_voodoo.h b/sound/soc/codecs/wm8994_voodoo.h
index 3cd7d4a..6e7d23f 100644
--- a/sound/soc/codecs/wm8994_voodoo.h
+++ b/sound/soc/codecs/wm8994_voodoo.h
@@ -6,8 +6,27 @@
* published by the Free Software Foundation.
*/
-bool is_path(int unified_path);
+#if defined(CONFIG_MACH_HERRING) || defined (CONFIG_SAMSUNG_GALAXYS) \
+ || defined (CONFIG_SAMSUNG_GALAXYSB) \
+ || defined (CONFIG_SAMSUNG_CAPTIVATE) \
+ || defined (CONFIG_SAMSUNG_VIBRANT) \
+ || defined (CONFIG_SAMSUNG_FASCINATE) \
+ || defined (CONFIG_SAMSUNG_EPIC)
+#define NEXUS_S
+#endif
+
+#ifdef CONFIG_FB_S3C_AMS701KA
+#define GALAXY_TAB
+#endif
+#ifdef CONFIG_M110S
+#define M110S
+#endif
+
+enum unified_path { HEADPHONES, RADIO_HEADPHONES, SPEAKER, MAIN_MICROPHONE };
+
+bool is_path(int unified_path);
+unsigned short tune_fll_value(unsigned short val);
unsigned int voodoo_hook_wm8994_write(struct snd_soc_codec *codec,
unsigned int reg, unsigned int value);
void voodoo_hook_fmradio_headset(void);
@@ -26,19 +45,3 @@ void update_fll_tuning(bool with_mute);
void update_mono_downmix(bool with_mute);
void update_dac_direct(bool with_mute);
void update_enable(void);
-
-unsigned short tune_fll_value(unsigned short val);
-
-#ifdef CONFIG_MACH_HERRING
-#define NEXUS_S
-#endif
-
-#ifdef CONFIG_FB_S3C_AMS701KA
-#define GALAXY_TAB
-#endif
-
-#ifdef CONFIG_M110S
-#define M110S
-#endif
-
-enum unified_path { HEADPHONES, RADIO_HEADPHONES, SPEAKER, MAIN_MICROPHONE };