diff options
author | SIMOND François <francois@lienweb.fr> | 2011-07-08 16:51:42 +0200 |
---|---|---|
committer | KalimochoAz <calimochoazucarado@gmail.com> | 2011-12-19 12:16:14 +0100 |
commit | 9706706582cd73ecbae2f267f5a22c17865a9f42 (patch) | |
tree | bc1d126efb104f649ee1ef9b62564baec177fc2b /sound/soc | |
parent | b1d3398cc9d4562119bf3c198c1803fc172526ae (diff) | |
download | kernel_samsung_crespo-9706706582cd73ecbae2f267f5a22c17865a9f42.zip kernel_samsung_crespo-9706706582cd73ecbae2f267f5a22c17865a9f42.tar.gz kernel_samsung_crespo-9706706582cd73ecbae2f267f5a22c17865a9f42.tar.bz2 |
Voodoo sound: driver v10
Improvement:
- HW EQ support: smooth activation/deactivation and gain changes
Bugfixes:
- HP volume smoothing loop on low levels with negative digital offsets
- wm8994_write logging on Nexus S
New supported devices:
- Galaxy Tab 7" Gingerbread Kernels support (based on M180S)
- Galaxy Tab 10.1 - beta
Diffstat (limited to 'sound/soc')
-rw-r--r-- | sound/soc/codecs/Kconfig.voodoo | 2 | ||||
-rw-r--r-- | sound/soc/codecs/wm8994_voodoo.c | 195 | ||||
-rw-r--r-- | sound/soc/codecs/wm8994_voodoo.h | 11 |
3 files changed, 160 insertions, 48 deletions
diff --git a/sound/soc/codecs/Kconfig.voodoo b/sound/soc/codecs/Kconfig.voodoo index 9d6882d..23ca597 100644 --- a/sound/soc/codecs/Kconfig.voodoo +++ b/sound/soc/codecs/Kconfig.voodoo @@ -1,6 +1,6 @@ menuconfig SND_VOODOO bool "Voodoo sound driver" - depends on SND_UNIVERSAL_WM8994 || SND_S3C24XX_SOC + depends on SND_UNIVERSAL_WM8994 || SND_S3C24XX_SOC || SND_SOC_WM8994_P3 default y help With this option enabled, the kernel compile an additionnal driver diff --git a/sound/soc/codecs/wm8994_voodoo.c b/sound/soc/codecs/wm8994_voodoo.c index c38e7be..d877d78 100644 --- a/sound/soc/codecs/wm8994_voodoo.c +++ b/sound/soc/codecs/wm8994_voodoo.c @@ -17,13 +17,13 @@ #include "wm8994_voodoo.h" #ifndef MODULE -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) && !defined(GALAXY_TAB) #include "wm8994_samsung.h" #else #include "wm8994.h" #endif #else -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) && !defined(GALAXY_TAB) #include "../wm8994_samsung.h" #else #include "../wm8994.h" @@ -55,7 +55,7 @@ short unsigned int debug_log_level = LOG_OFF; #ifdef CONFIG_SND_VOODOO_HP_LEVEL_CONTROL unsigned short hp_level[2] = { CONFIG_SND_VOODOO_HP_LEVEL, - CONFIG_SND_VOODOO_HP_LEVEL };; + CONFIG_SND_VOODOO_HP_LEVEL }; #endif #ifdef CONFIG_SND_VOODOO_FM @@ -79,7 +79,9 @@ bool enable = false; bool dac_osr128 = true; bool adc_osr128 = false; +#ifndef GALAXY_TAB_TEGRA bool fll_tuning = true; +#endif bool dac_direct = true; bool mono_downmix = false; @@ -134,7 +136,7 @@ static ssize_t headphone_eq_b##band##_gain_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ - return sprintf(buf, "%d\n", eq_gains[band-1]); \ + return sprintf(buf, "%d\n", eq_gains[band - 1]); \ } #define DECLARE_EQ_GAIN_STORE(band) \ @@ -145,8 +147,11 @@ static ssize_t headphone_eq_b##band##_gain_store(struct device *dev, \ short new_gain; \ if (sscanf(buf, "%hd", &new_gain) == 1) { \ if (new_gain >= -12 && new_gain <= 12) { \ - eq_gains[band-1] = new_gain; \ - update_headphone_eq(false); \ + smooth_apply_eq_band_gain(band - 1, \ + eq_gains[band - 1], \ + new_gain, \ + headphone_eq); \ + eq_gains[band - 1] = new_gain; \ } \ } \ return size; \ @@ -206,7 +211,7 @@ void update_hpvol(bool with_fade) unsigned short val; unsigned short i; short steps; - unsigned short hp_level_old[2]; + int hp_level_old[2]; unsigned short hp_level_registers[2] = { WM8994_LEFT_OUTPUT_VOLUME, WM8994_RIGHT_OUTPUT_VOLUME }; @@ -218,9 +223,9 @@ void update_hpvol(bool with_fade) || (wm8994->codec_state & CALL_ACTIVE)) return; - bypass_write_hook = true; if (!with_fade) { + bypass_write_hook = true; write_hpvol(hpvol(0), hpvol(1)); bypass_write_hook = false; return; @@ -234,9 +239,12 @@ void update_hpvol(bool with_fade) val &= ~(WM8994_HPOUT1L_MUTE_N_MASK); hp_level_old[i] = val + (digital_gain / 1000); + if (hp_level_old[i] < 0) + hp_level_old[i] = 0; + if (debug_log(LOG_INFOS)) - printk("Voodoo sound: previous hp_level[%hu]: %hu\n", - i, val); + printk("Voodoo sound: previous hp_level[%hu]: %d\n", + i, hp_level_old[i]); } // calculate number of steps for volume fade @@ -258,13 +266,14 @@ void update_hpvol(bool with_fade) printk("Voodoo sound: volume: %hu\n", (hpvol(0) - steps)); + bypass_write_hook = true; write_hpvol(hpvol(0) - steps, hpvol(1) - steps); + bypass_write_hook = false; if (steps != 0) udelay(1000); } - bypass_write_hook = false; } #endif @@ -480,9 +489,14 @@ bool is_path(int unified_path) || wm8994->cur_path == HP_NO_MIC); #else #ifdef GALAXY_TAB +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) + return (wm8994->cur_path == HP + || wm8994->cur_path == HP_NO_MIC); +#else return (wm8994->cur_path == HP3P || wm8994->cur_path == HP4P || wm8994->fmradio_path == FMR_HP); +#endif #else #ifdef M110S #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) @@ -492,6 +506,10 @@ bool is_path(int unified_path) return (wm8994->cur_path == HP); #endif #else +#ifdef GALAXY_TAB_TEGRA + return (wm8994->cur_path == HP + || wm8994->cur_path == HP_NO_MIC); +#else #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) return (wm8994->cur_path == HP || wm8994->cur_path == HP_NO_MIC @@ -503,6 +521,7 @@ bool is_path(int unified_path) #endif #endif #endif +#endif // FM Radio on headphones case RADIO_HEADPHONES: @@ -512,15 +531,18 @@ bool is_path(int unified_path) #ifdef M110S return false; #else +#ifdef GALAXY_TAB_TEGRA + return false; +#else #ifdef GALAXY_TAB - return (wm8994->codec_state & FMRADIO_ACTIVE) - && (wm8994->fmradio_path == FMR_HP); + return false; #else return (wm8994->codec_state & FMRADIO_ACTIVE) && (wm8994->fmradio_path == FMR_HP); #endif #endif #endif +#endif // Standard recording presets // for M110S Gingerbread: added check non call @@ -533,7 +555,8 @@ bool is_path(int unified_path) return false; } -bool is_path_media_or_fm_no_call_no_record() { +bool is_path_media_or_fm_no_call_no_record() +{ DECLARE_WM8994(codec); @@ -636,6 +659,7 @@ void update_osr128(bool with_mute) bypass_write_hook = false; } +#ifndef GALAXY_TAB_TEGRA unsigned short fll_tuning_get_value(unsigned short val) { val = (val >> WM8994_FLL1_GAIN_WIDTH << WM8994_FLL1_GAIN_WIDTH); @@ -653,6 +677,7 @@ void update_fll_tuning(bool with_mute) wm8994_write(codec, WM8994_FLL1_CONTROL_4, val); bypass_write_hook = false; } +#endif unsigned short mono_downmix_get_value(unsigned short val, bool can_reverse) { @@ -699,8 +724,7 @@ unsigned short dac_direct_get_value(unsigned short val, bool can_reverse) if (val == WM8994_DAC1L_TO_MIXOUTL) return WM8994_DAC1L_TO_HPOUT1L; } else { - if (val == WM8994_DAC1L_TO_HPOUT1L - && can_reverse) + if (val == WM8994_DAC1L_TO_HPOUT1L && can_reverse) return WM8994_DAC1L_TO_MIXOUTL; } } @@ -742,8 +766,9 @@ unsigned short digital_gain_get_value(unsigned short val) if (debug_log(LOG_INFOS)) printk("Voodoo sound: digital gain: %d mdB, " - "steps: %d, real AIF gain: %d mdB\n", - digital_gain, i, i * step); + "%d mdB steps: %d, " + "real AIF gain: %d mdB\n", + digital_gain, step, i, i * step); } } @@ -766,14 +791,10 @@ void update_digital_gain(bool with_mute) bypass_write_hook = false; } -void update_headphone_eq(bool with_mute) +void update_headphone_eq(bool update_bands) { int gains_1; int gains_2; - int i; - int j; - int k = 0; - int first_reg = WM8994_AIF1_DAC1_EQ_BAND_1_A; if (!is_path_media_or_fm_no_call_no_record()) { // don't apply the EQ @@ -782,8 +803,8 @@ void update_headphone_eq(bool with_mute) if (debug_log(LOG_INFOS)) printk("Voodoo sound: EQ gains (dB): %hd, %hd, %hd, %hd, %hd\n", - eq_gains[0], eq_gains[1], eq_gains[2], - eq_gains[3], eq_gains[4]); + eq_gains[0], eq_gains[1], eq_gains[2], + eq_gains[3], eq_gains[4]); gains_1 = ((eq_gains[0] + 12) << WM8994_AIF1DAC1_EQ_B1_GAIN_SHIFT) | @@ -802,6 +823,17 @@ void update_headphone_eq(bool with_mute) if (!headphone_eq) return; + if (update_bands) + update_headphone_eq_bands(); +} + +void update_headphone_eq_bands() +{ + int i; + int j; + int k = 0; + int first_reg = WM8994_AIF1_DAC1_EQ_BAND_1_A; + for (i = 0; i < ARRAY_SIZE(eq_band_values); i++) { if (debug_log(LOG_INFOS)) printk("Voodoo sound: send EQ Band %d\n", i + 1); @@ -814,6 +846,34 @@ void update_headphone_eq(bool with_mute) } } +void smooth_apply_eq_band_gain(int band, int start, int end, bool current_state) +{ + if (debug_log(LOG_INFOS)) + printk("Voodoo sound: EQ smooth transition for Band %d " + "from %d to %d\n", band + 1, start, end); + + if (start == end) { + if (end != 0) + update_headphone_eq(true); + else + update_headphone_eq(false); + return; + } + + if (current_state) + update_headphone_eq_bands(); + + while (start != end) { + if (start < end) + start++; + else + start--; + + eq_gains[band] = start; + update_headphone_eq(false); + } +} + void update_stereo_expansion(bool with_mute) { short unsigned int val; @@ -864,6 +924,9 @@ void apply_saturation_prevention_drc() || digital_gain >= 0)) return; + if (debug_log(LOG_INFOS)) + printk("Voodoo sound: apply saturation prevention DRC\n"); + // configure the DRC to avoid saturation: not actually compress signal // gain is unmodified. Should affect only what's higher than 0 dBFS @@ -907,8 +970,8 @@ void apply_saturation_prevention_drc() if (debug_log(LOG_INFOS)) printk("Voodoo sound: digital gain: %d mdB, " - "steps: %d, real DRC gain: %d mdB\n", - digital_gain, i, i * step); + "%d mdB steps: %d, real DRC gain: %d mdB\n", + digital_gain, step, i, i * step); } wm8994_write(codec, WM8994_AIF1_DRC1_4, val); @@ -1018,10 +1081,12 @@ DECLARE_BOOL_STORE_UPDATE_WITH_MUTE(adc_osr128, update_osr128, false); +#ifndef GALAXY_TAB_TEGRA DECLARE_BOOL_SHOW(fll_tuning); DECLARE_BOOL_STORE_UPDATE_WITH_MUTE(fll_tuning, update_fll_tuning, false); +#endif DECLARE_BOOL_SHOW(mono_downmix); DECLARE_BOOL_STORE_UPDATE_WITH_MUTE(mono_downmix, @@ -1068,9 +1133,41 @@ static ssize_t digital_gain_store(struct device *dev, } DECLARE_BOOL_SHOW(headphone_eq); -DECLARE_BOOL_STORE_UPDATE_WITH_MUTE(headphone_eq, - update_headphone_eq, - false); +static ssize_t headphone_eq_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + unsigned short state; + bool current_state; + int i; + short eq_gains_copy[ARRAY_SIZE(eq_gains)]; + + if (sscanf(buf, "%hu", &state) == 1) { + current_state = state == 0 ? false : true; + if (debug_log(LOG_INFOS)) + printk("Voodoo sound: EQ activation: %u\n", state); + + if (current_state) { + // fade from 0dB each EQ band + headphone_eq = current_state; + for (i = 0; i < ARRAY_SIZE(eq_bands); i++) + smooth_apply_eq_band_gain(i, 0, eq_gains[i], + current_state); + } else { + // fade to 0dB each EQ band + for (i = 0; i < ARRAY_SIZE(eq_bands); i++) { + eq_gains_copy[i] = eq_gains[i]; + smooth_apply_eq_band_gain(i, eq_gains[i], 0, + current_state); + } + // restore original gains in driver memory not codec + for (i = 0; i < ARRAY_SIZE(eq_bands); i++) + eq_gains[i] = eq_gains_copy[i]; + headphone_eq = current_state; + } + } + return size; +} DECLARE_EQ_GAIN_SHOW(1); DECLARE_EQ_GAIN_STORE(1); @@ -1133,12 +1230,12 @@ static ssize_t headphone_eq_bands_values_store(struct device *dev, for (i = 0; i < ARRAY_SIZE(eq_band_coef_names); i++) { // loop through band coefficient letters if (strncmp(eq_band_coef_names[i], coef_name, 2) == 0) { - if (eq_bands[band-1] == 3 && i == 3) + if (eq_bands[band - 1] == 3 && i == 3) // deal with high and low shelves - eq_band_values[band-1][2] = val; + eq_band_values[band - 1][2] = val; else // parametric bands - eq_band_values[band-1][i] = val; + eq_band_values[band - 1][i] = val; if (debug_log(LOG_INFOS)) printk("Voodoo sound: read EQ from " @@ -1271,7 +1368,7 @@ static ssize_t store_wm8994_write(struct device *dev, while (sscanf(buf, "%hx %hx%n", ®, &val, &bytes_read) == 2) { buf += bytes_read; - if (debug_log(LOG_INFOS)); + if (debug_log(LOG_INFOS)) printk("Voodoo sound: read from sysfs: %X, %X\n", reg, val); @@ -1352,9 +1449,11 @@ static DEVICE_ATTR(adc_osr128, S_IRUGO | S_IWUGO, adc_osr128_show, adc_osr128_store); +#ifndef GALAXY_TAB_TEGRA static DEVICE_ATTR(fll_tuning, S_IRUGO | S_IWUGO, fll_tuning_show, fll_tuning_store); +#endif static DEVICE_ATTR(dac_direct, S_IRUGO | S_IWUGO, dac_direct_show, @@ -1448,7 +1547,9 @@ static struct attribute *voodoo_sound_attributes[] = { #endif &dev_attr_dac_osr128.attr, &dev_attr_adc_osr128.attr, +#ifndef GALAXY_TAB_TEGRA &dev_attr_fll_tuning.attr, +#endif &dev_attr_dac_direct.attr, &dev_attr_digital_gain.attr, &dev_attr_headphone_eq.attr, @@ -1637,9 +1738,11 @@ unsigned int voodoo_hook_wm8994_write(struct snd_soc_codec *codec_, if (reg == WM8994_OVERSAMPLING) value = osr128_get_value(value); +#ifndef GALAXY_TAB_TEGRA // global Anti-Jitter tuning if (reg == WM8994_FLL1_CONTROL_4) value = fll_tuning_get_value(value); +#endif // global Mono downmix tuning if (reg == WM8994_AIF1_DAC1_FILTERS_1 @@ -1663,7 +1766,7 @@ unsigned int voodoo_hook_wm8994_write(struct snd_soc_codec *codec_, || reg == WM8994_AIF2_DAC_FILTERS_1) { bypass_write_hook = true; apply_saturation_prevention_drc(); - update_headphone_eq(false); + update_headphone_eq(true); update_stereo_expansion(false); bypass_write_hook = false; } @@ -1684,29 +1787,33 @@ unsigned int voodoo_hook_wm8994_write(struct snd_soc_codec *codec_, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) "codec_state=%u, stream_state=%u, " "cur_path=%i, rec_path=%i, " -#ifndef M110S +#if !defined(M110S) && !defined(GALAXY_TAB_TEGRA) "fmradio_path=%i, fmr_mix_path=%i, " #endif +#ifndef GALAXY_TAB "input_source=%i, " -#ifndef M110S +#endif +#if !defined(M110S) && !defined(GALAXY_TAB_TEGRA) && !defined(GALAXY_TAB) "output_source=%i, " #endif "power_state=%i\n", reg, value, wm8994->codec_state, wm8994->stream_state, -#ifndef M110S +#if !defined(M110S) && !defined(GALAXY_TAB_TEGRA) wm8994->fmradio_path, wm8994->fmr_mix_path, #endif wm8994->cur_path, wm8994->rec_path, +#ifndef GALAXY_TAB wm8994->input_source, -#ifndef M110S +#endif +#if !defined(M110S) && !defined(GALAXY_TAB_TEGRA) && !defined(GALAXY_TAB) wm8994->output_source, #endif wm8994->power_state); #else "codec_state=%u, stream_state=%u, " "cur_path=%i, rec_path=%i, " -#ifndef M110S +#if !defined(M110S) && !defined(GALAXY_TAB_TEGRA) "fmradio_path=%i, fmr_mix_path=%i, " #endif #ifdef CONFIG_S5PC110_KEPLER_BOARD @@ -1715,14 +1822,14 @@ unsigned int voodoo_hook_wm8994_write(struct snd_soc_codec *codec_, "Fac_SUB_MIC_state=%i, TTY_state=%i, " #endif "power_state=%i, " -#ifndef M110S +#if !defined(M110S) && !defined(GALAXY_TAB_TEGRA) "recognition_active=%i, ringtone_active=%i" #endif "\n", reg, value, wm8994->codec_state, wm8994->stream_state, wm8994->cur_path, wm8994->rec_path, -#ifndef M110S +#if !defined(M110S) && !defined(GALAXY_TAB_TEGRA) wm8994->fmradio_path, wm8994->fmr_mix_path, #endif #ifdef CONFIG_S5PC110_KEPLER_BOARD @@ -1731,11 +1838,11 @@ unsigned int voodoo_hook_wm8994_write(struct snd_soc_codec *codec_, wm8994->Fac_SUB_MIC_state, wm8994->TTY_state, #endif wm8994->power_state -#ifndef M110S +#if !defined(M110S) && !defined(GALAXY_TAB_TEGRA) ,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 ef73e28..578f8e8 100644 --- a/sound/soc/codecs/wm8994_voodoo.h +++ b/sound/soc/codecs/wm8994_voodoo.h @@ -6,7 +6,7 @@ * published by the Free Software Foundation. */ -#define VOODOO_SOUND_VERSION 9 +#define VOODOO_SOUND_VERSION 10 #if defined(CONFIG_MACH_HERRING) || defined (CONFIG_SAMSUNG_GALAXYS) \ || defined (CONFIG_SAMSUNG_GALAXYSB) \ @@ -17,7 +17,7 @@ #define NEXUS_S #endif -#ifdef CONFIG_FB_S3C_AMS701KA +#if defined(CONFIG_FB_S3C_AMS701KA) || defined(CONFIG_KOR_MODEL_M180S) #define GALAXY_TAB #endif @@ -25,6 +25,10 @@ #define M110S #endif +#ifdef CONFIG_MACH_SAMSUNG_VARIATION_TEGRA +#define GALAXY_TAB_TEGRA +#endif + #ifdef CONFIG_TDMB_T3700 #define M110S #endif @@ -58,5 +62,6 @@ void update_mono_downmix(bool with_mute); void update_dac_direct(bool with_mute); void update_digital_gain(bool with_mute); void update_stereo_expansion(bool with_mute); -void update_headphone_eq(bool with_mute); +void update_headphone_eq(bool update_bands); +void update_headphone_eq_bands(void); void update_enable(void); |