Skip to content

Commit

Permalink
Voodoo sound: introducing usage of the ReTune hardware parametric EQ
Browse files Browse the repository at this point in the history
This first extension allow usage of the parametric hardware EQ in order to reduce harshness found in high frequencies.
With the current setup, high frequencies around 20kHz create an associated white noise and tend to make highs fatiguing and unclean.
I don't know if it's a limit of the oversampling abilities of the codec, but the method employed here is surprisingly effective.

The only drawback is that alter (reduce) the high frequency response for very high frequencies. It can slightly affect the brightness and it's probably not recommended to use it if your headphone already lack brightness.
However it's tuned to mostly removes noise artifacts and frequencies which are not reproduced accurately in the default codec config.

This anti-alias filter can be tweaked live through sysfs as simple user.
filename: /sys/devices/virtual/voodoo_sound/parametric_equalizer/anti_alias_filter

0: anti-alias filter disabled
1: anti-alias filter enabled, simple mode. 1 high-shelf
2: anti-alias filter enabled, advanced mode. 1 parametric EQ band + 1 high-shelf

For novice listeners, this filter's effect can be difficult to identify.
Testing with udial.wav make a very clear demonstration of its efficiency ;)
  • Loading branch information
supercurio committed Oct 23, 2010
1 parent 62e580c commit df44533
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 6 deletions.
89 changes: 83 additions & 6 deletions Kernel/sound/soc/codecs/wm8994_aries.c
Expand Up @@ -172,9 +172,12 @@ extern short int get_headset_status(void); // For ear-jack control(MIC-Bias)
extern void set_recording_status(int value); // For preventing MIC Bias off on using MIC.


#ifdef CONFIG_SND_VOODOO_SOUND_HEADPHONE_AMP_GAIN
// Voodoo sound
#ifdef CONFIG_SND_VOODOO_SOUND_RETUNE_EQ
// by default the anti-alias filter is disabled
unsigned short voodoo_anti_alias_filter = 0;
#endif

#ifdef CONFIG_SND_VOODOO_SOUND_HEADPHONE_AMP_GAIN
// Creating variables which we will use to save the headphone amplifier
// gain chose by the user through sysfs interface
// min: 0x0, max 3B ( 3C -> 3F = saturation & distortion )
Expand All @@ -190,9 +193,16 @@ struct device *voodoo_sound_dev;

// Voodoo sound: headphone amplifier gain

static void voodoo_update_headphone_volumes()
void voodoo_update_headphone_volumes(void)
{
unsigned short val;

// hard limit to 61 because 62 and 63 introduce distortion
if (voodoo_headphone_left_volume > 62)
voodoo_headphone_left_volume = 62;
if (voodoo_headphone_right_volume > 62)
voodoo_headphone_right_volume = 62;

// we don't need the Volume Update flag when sending the first volume
//printk("Voodoo sound: setting headphone volume: left %u\n", voodoo_headphone_left_volume);
val = (WM8994_HPOUT1L_MUTE_N | voodoo_headphone_left_volume);
Expand Down Expand Up @@ -247,7 +257,6 @@ static ssize_t gain_store(struct device *dev,
static DEVICE_ATTR(gain_lr,0666, gain_lr_show, gain_lr_store);
// create the sysfs device to allow read and write
static DEVICE_ATTR(gain,0666, gain_show, gain_store);

#endif


Expand All @@ -271,7 +280,7 @@ static ssize_t wm8994_write_store(struct device *dev,
{
short unsigned int register_address = 0x0;
short unsigned int val = 0x0;
if (sscanf(buf, "%hx %hx", &register_address, &val) != 1)
if (sscanf(buf, "%hx %hx", &register_address, &val) == 2)
wm8994_write(voodoo_codec, register_address, val);

return size;
Expand All @@ -281,6 +290,61 @@ static DEVICE_ATTR(wm8994_write,0600, wm8994_write_show, wm8994_write_store);
#endif


#ifdef CONFIG_SND_VOODOO_SOUND_RETUNE_EQ
// Voodoo sound: use the hardware parametric equalizer

void voodoo_update_anti_alias_filter(void)
{

// Use the parametric EQ to create an anti-alias filter
// printk("Voodoo sound: applying anti-alias filter\n");

if (voodoo_anti_alias_filter == 1)
{
// anti-alias 1 (only high-shelf)
wm8994_write(voodoo_codec, 0x480, 0x6319);
wm8994_write(voodoo_codec, 0x481, 0x6000);
wm8994_write(voodoo_codec, 0x491, 0xF692);
wm8994_write(voodoo_codec, 0x492, 0x0400);
wm8994_write(voodoo_codec, 0x493, 0x1A48);
}
if (voodoo_anti_alias_filter == 2)
{
// anti alias 2 (1 parametric band + high-shelf)
wm8994_write(voodoo_codec, 0x480, 0x6319);
wm8994_write(voodoo_codec, 0x481, 0x0000);
wm8994_write(voodoo_codec, 0x48D, 0xE386);
wm8994_write(voodoo_codec, 0x48E, 0xF1B2);
wm8994_write(voodoo_codec, 0x48F, 0x040A);
wm8994_write(voodoo_codec, 0x490, 0x06B7);
wm8994_write(voodoo_codec, 0x491, 0xF474);
wm8994_write(voodoo_codec, 0x492, 0x0400);
wm8994_write(voodoo_codec, 0x493, 0x11D0);
}
}

static ssize_t anti_alias_filter_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf,"%hu\n",voodoo_anti_alias_filter);
return 0;
}

static ssize_t anti_alias_filter_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
sscanf(buf, "%hu", &voodoo_anti_alias_filter);
if (voodoo_anti_alias_filter > 2)
voodoo_anti_alias_filter = 0;

voodoo_update_anti_alias_filter();
return size;
}

static DEVICE_ATTR(anti_alias_filter,0666, anti_alias_filter_show, anti_alias_filter_store);
#endif



// Voodoo sound initialization
#ifdef CONFIG_SND_VOODOO_SOUND
Expand All @@ -304,6 +368,15 @@ int voodoo_sound_init(struct snd_soc_codec *codec)
pr_err("Failed to create device file(%s)!\n", dev_attr_gain.attr.name);
#endif

#ifdef CONFIG_SND_VOODOO_SOUND_RETUNE_EQ
printk("Voodoo sound: ReTune parametric EQ activated\n");
voodoo_sound_dev = device_create(voodoo_sound_class, NULL, 0, NULL, "parametric_equalizer");
if (IS_ERR(voodoo_sound_dev))
pr_err("Failed to create device(voodoo_sound_dev)!\n");
if (device_create_file(voodoo_sound_dev, &dev_attr_anti_alias_filter) < 0)
pr_err("Failed to create device file(%s)!\n", dev_attr_anti_alias_filter.attr.name);
#endif

#ifdef CONFIG_SND_VOODOO_SOUND_WM8994_WRITE
printk("Voodoo sound: wm8994 direct write to codec interface activated\n");
voodoo_sound_dev = device_create(voodoo_sound_class, NULL, 0, NULL, "wm8994_codec");
Expand Down Expand Up @@ -1557,7 +1630,11 @@ void wm8994_set_playback_headset(struct snd_soc_codec *codec)
val |= (WM8994_HPOUT1_VU | WM8994_HPOUT1R_MUTE_N | TUNING_MP3_OUTPUTR_VOL);
#endif
wm8994_write(codec, WM8994_RIGHT_OUTPUT_VOLUME, val);



#ifdef CONFIG_SND_VOODOO_SOUND_RETUNE_EQ
voodoo_update_anti_alias_filter();
#endif

val = wm8994_read(codec, WM8994_LEFT_OPGA_VOLUME);
val &= ~(WM8994_MIXOUTL_MUTE_N_MASK | WM8994_MIXOUTL_VOL_MASK);
Expand Down
8 changes: 8 additions & 0 deletions Kernel/sound/soc/s3c24xx/Kconfig
Expand Up @@ -111,6 +111,14 @@ config SND_VOODOO_SOUND_HEADPHONE_AMP_GAIN
Say Y if you want to activate control of the headphone gain through
the sysfs interface

config SND_VOODOO_SOUND_RETUNE_EQ
bool "ReTune parametric hardware equalizer"
depends on SND_VOODOO_SOUND
default y
help
Say Y if you want to activate Wolfson ReTune paremetric hardware
equalizer controls

config SND_VOODOO_SOUND_WM8994_READ
bool "Expose the wm8994_read function"
depends on SND_VOODOO_SOUND
Expand Down

0 comments on commit df44533

Please sign in to comment.