aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorSIMOND François <francois@lienweb.fr>2011-07-08 16:51:42 +0200
committerKalimochoAz <calimochoazucarado@gmail.com>2011-12-19 12:16:14 +0100
commit9706706582cd73ecbae2f267f5a22c17865a9f42 (patch)
treebc1d126efb104f649ee1ef9b62564baec177fc2b /sound/soc
parentb1d3398cc9d4562119bf3c198c1803fc172526ae (diff)
downloadkernel_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.voodoo2
-rw-r--r--sound/soc/codecs/wm8994_voodoo.c195
-rw-r--r--sound/soc/codecs/wm8994_voodoo.h11
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", &reg, &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);