diff options
author | SIMOND François <francois@lienweb.fr> | 2011-04-25 06:49:14 +0200 |
---|---|---|
committer | KalimochoAz <calimochoazucarado@gmail.com> | 2011-12-19 12:15:48 +0100 |
commit | c66fbe8305d97ed8b4d0bff029d38ab57e09b05b (patch) | |
tree | 24ce67f231fbc9e02b7c7dffdc59379bb316b6d3 /sound/soc/codecs | |
parent | 1b10ba19971bdc681faceb2187060d5a8371dd6c (diff) | |
download | kernel_samsung_crespo-c66fbe8305d97ed8b4d0bff029d38ab57e09b05b.zip kernel_samsung_crespo-c66fbe8305d97ed8b4d0bff029d38ab57e09b05b.tar.gz kernel_samsung_crespo-c66fbe8305d97ed8b4d0bff029d38ab57e09b05b.tar.bz2 |
Voodoo sound: driver v8
- Fixes DAC direct not being applied in several situations
- Fixes 1 channel only on Captivate headphone+mic calls
- Add full support for Samsung Gingerbread kernels
including complete FM radio tunings
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r-- | sound/soc/codecs/Kconfig.voodoo | 8 | ||||
-rw-r--r-- | sound/soc/codecs/wm8994_voodoo.c | 201 | ||||
-rw-r--r-- | sound/soc/codecs/wm8994_voodoo.h | 37 |
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 }; |