summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/SOURCES3
-rw-r--r--apps/lang/english.lang137
-rw-r--r--apps/menus/audiohw_eq_menu.c244
-rw-r--r--apps/menus/exported_menus.h3
-rw-r--r--apps/menus/sound_menu.c50
-rw-r--r--apps/plugin.c3
-rw-r--r--apps/plugin.h7
-rw-r--r--apps/plugins/mpegplayer/mpeg_settings.c35
-rw-r--r--apps/settings.c35
-rw-r--r--apps/settings.h21
-rw-r--r--apps/settings_list.c100
-rw-r--r--firmware/drivers/audio/wm8978.c122
-rw-r--r--firmware/export/audiohw.h252
-rw-r--r--firmware/export/config/gigabeats.h3
-rw-r--r--firmware/export/sound.h62
-rw-r--r--firmware/export/wm8978.h13
-rw-r--r--firmware/sound.c347
-rw-r--r--uisimulator/sdl/sound.c17
18 files changed, 1389 insertions, 65 deletions
diff --git a/apps/SOURCES b/apps/SOURCES
index 2642fa16b1..2bd4018751 100644
--- a/apps/SOURCES
+++ b/apps/SOURCES
@@ -16,6 +16,9 @@ menus/menu_common.c
menus/display_menu.c
menus/theme_menu.c
#if CONFIG_CODEC == SWCODEC
+#ifdef HAVE_WM8978
+menus/audiohw_eq_menu.c
+#endif
menus/eq_menu.c
buffering.c
voice_thread.c
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index c079a4affd..4a4fb2c73a 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -13595,3 +13595,140 @@
radio: ""
</voice>
</phrase>
+<phrase>
+ id: LANG_HW_EQ_TONE_CONTROLS
+ desc: in sound_menu, hardware equalizer tone controls
+ user: core
+ <source>
+ *: none
+ gigabeats: "Tone Controls"
+ </source>
+ <dest>
+ *: none
+ gigabeats: "Tone Controls"
+ </dest>
+ <voice>
+ *: none
+ gigabeats: "Tone Controls"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_HW_EQ_TONE_CONTROLS_ADVANCED
+ desc: in sound_menu, advanced settings for hardware equalizer tone controls
+ user: core
+ <source>
+ *: none
+ gigabeats: "Advanced Tone Control Settings"
+ </source>
+ <dest>
+ *: none
+ gigabeats: "Advanced Tone Control Settings"
+ </dest>
+ <voice>
+ *: none
+ gigabeats: "Advanced Tone Control Settings"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_HW_EQ_GAIN
+ desc: in sound_menu, hardware equalizer tone controls filter gain
+ user: core
+ <source>
+ *: none
+ gigabeats: "Band %d Gain"
+ </source>
+ <dest>
+ *: none
+ gigabeats: "Band %d Gain"
+ </dest>
+ <voice>
+ *: none
+ gigabeats: "Band Gain"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_HW_EQ_FREQUENCY
+ desc: in sound_menu, hardware equalizer tone controls shelf filter cutoff frequency
+ user: core
+ <source>
+ *: none
+ gigabeats: "Band %d Frequency"
+ </source>
+ <dest>
+ *: none
+ gigabeats: "Band %d Frequency"
+ </dest>
+ <voice>
+ *: none
+ gigabeats: "Band Frequency"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_HW_EQ_WIDTH
+ desc: in sound_menu, hardware equalizer tone controls peak bandwith setting
+ user: core
+ <source>
+ *: none
+ gigabeats: "Band %d Width"
+ </source>
+ <dest>
+ *: none
+ gigabeats: "Band %d Width"
+ </dest>
+ <voice>
+ *: none
+ gigabeats: "Band Width"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_HW_EQ_WIDTH_NARROW
+ desc: in sound_menu, hardware equalizer tone controls narrow bandwith setting
+ user: core
+ <source>
+ *: none
+ gigabeats: "Narrow"
+ </source>
+ <dest>
+ *: none
+ gigabeats: "Narrow"
+ </dest>
+ <voice>
+ *: none
+ gigabeats: "Narrow"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_HW_EQ_WIDTH_WIDE
+ desc: in sound_menu, hardware equalizer tone controls wide bandwidth setting
+ user: core
+ <source>
+ *: none
+ gigabeats: "Wide"
+ </source>
+ <dest>
+ *: none
+ gigabeats: "Wide"
+ </dest>
+ <voice>
+ *: none
+ gigabeats: "Wide"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_DEPTH_3D
+ desc: in sound_menu, amount of 3D enhancement effect
+ user: core
+ <source>
+ *: none
+ gigabeats: "3-D Enhancement"
+ </source>
+ <dest>
+ *: none
+ gigabeats: "3-D Enhancement"
+ </dest>
+ <voice>
+ *: none
+ gigabeats: "3-D Enhancement"
+ </voice>
+</phrase>
+
diff --git a/apps/menus/audiohw_eq_menu.c b/apps/menus/audiohw_eq_menu.c
new file mode 100644
index 0000000000..1027d6a0b8
--- /dev/null
+++ b/apps/menus/audiohw_eq_menu.c
@@ -0,0 +1,244 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2010 Michael Sevakis
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include <stdio.h>
+#include "config.h"
+#include "sound.h"
+#include "settings.h"
+#include "lang.h"
+#include "menu.h"
+#include "talk.h"
+
+#define HW_EQ_IDX(band, setting) ((void *)(((setting) << 8) | (band)))
+#define HW_EQ_IDX_BAND(data) ((uint8_t)(uintptr_t)(data))
+#define HW_EQ_IDX_SETTING(data) ((uint8_t)((uintptr_t)(data) >> 8))
+
+static unsigned short hw_eq_setting_lang_ids[AUDIOHW_EQ_SETTING_NUM] =
+{
+ LANG_HW_EQ_GAIN,
+#ifdef AUDIOHW_HAVE_EQ_FREQUENCY
+ LANG_HW_EQ_FREQUENCY,
+#endif
+#ifdef AUDIOHW_HAVE_EQ_WIDTH
+ LANG_HW_EQ_WIDTH,
+#endif
+};
+
+static char * hw_eq_get_name(int selected_item, void * data, char *buffer)
+{
+ snprintf(buffer, MAX_PATH,
+ str(hw_eq_setting_lang_ids[HW_EQ_IDX_SETTING(data)]),
+ HW_EQ_IDX_BAND(data) + 1);
+ return buffer;
+ (void)selected_item;
+}
+
+static int hw_eq_speak_item(int selected_item, void * data)
+{
+ talk_id(hw_eq_setting_lang_ids[HW_EQ_IDX_SETTING(data)], false);
+ talk_number(HW_EQ_IDX_BAND(data) + 1, true);
+ return 0;
+ (void)selected_item;
+}
+
+static int hw_eq_do_band_setting(void *param)
+{
+ int band = HW_EQ_IDX_BAND(param);
+ int setting = HW_EQ_IDX_SETTING(param);
+ char desc[MAX_PATH];
+ struct menu_callback_with_desc cbwdesc =
+ {
+ .menu_callback = NULL,
+ .desc = hw_eq_get_name(0, param, desc),
+ .icon_id = Icon_NOICON
+ };
+ struct menu_item_ex item =
+ {
+ .flags = MT_SETTING_W_TEXT | MENU_HAS_DESC,
+ { .variable = (void*)(&global_settings.hw_eq_bands[band].gain + setting) },
+ { .callback_and_desc = &cbwdesc }
+ };
+ do_setting_from_menu(&item, NULL);
+ return 0;
+}
+
+MENUITEM_FUNCTION_DYNTEXT(hw_eq_band1_gain, MENU_FUNC_USEPARAM,
+ hw_eq_do_band_setting,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND1, AUDIOHW_EQ_GAIN),
+ hw_eq_get_name, hw_eq_speak_item,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND1, AUDIOHW_EQ_GAIN),
+ NULL, Icon_Menu_setting);
+#ifdef AUDIOHW_HAVE_EQ_BAND1_FREQUENCY
+MENUITEM_FUNCTION_DYNTEXT(hw_eq_band1_frequency, MENU_FUNC_USEPARAM,
+ hw_eq_do_band_setting,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND1, AUDIOHW_EQ_FREQUENCY),
+ hw_eq_get_name, hw_eq_speak_item,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND1, AUDIOHW_EQ_FREQUENCY),
+ NULL, Icon_NOICON);
+#endif
+#ifdef AUDIOHW_HAVE_EQ_BAND2
+MENUITEM_FUNCTION_DYNTEXT(hw_eq_band2_gain, MENU_FUNC_USEPARAM,
+ hw_eq_do_band_setting,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND2, AUDIOHW_EQ_GAIN),
+ hw_eq_get_name, hw_eq_speak_item,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND2, AUDIOHW_EQ_GAIN),
+ NULL, Icon_Menu_setting);
+#ifdef AUDIOHW_HAVE_EQ_BAND2_FREQUENCY
+MENUITEM_FUNCTION_DYNTEXT(hw_eq_band2_frequency, MENU_FUNC_USEPARAM,
+ hw_eq_do_band_setting,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND2, AUDIOHW_EQ_FREQUENCY),
+ hw_eq_get_name, hw_eq_speak_item,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND2, AUDIOHW_EQ_FREQUENCY),
+ NULL, Icon_NOICON);
+#endif
+#ifdef AUDIOHW_HAVE_EQ_BAND2_WIDTH
+MENUITEM_FUNCTION_DYNTEXT(hw_eq_band2_width, MENU_FUNC_USEPARAM,
+ hw_eq_do_band_setting,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND2, AUDIOHW_EQ_WIDTH),
+ hw_eq_get_name, hw_eq_speak_item,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND2, AUDIOHW_EQ_WIDTH),
+ NULL, Icon_NOICON);
+#endif
+#endif /* AUDIOHW_HAVE_EQ_BAND2 */
+#ifdef AUDIOHW_HAVE_EQ_BAND3
+MENUITEM_FUNCTION_DYNTEXT(hw_eq_band3_gain, MENU_FUNC_USEPARAM,
+ hw_eq_do_band_setting,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND3, AUDIOHW_EQ_GAIN),
+ hw_eq_get_name, hw_eq_speak_item,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND3, AUDIOHW_EQ_GAIN),
+ NULL, Icon_Menu_setting);
+#ifdef AUDIOHW_HAVE_EQ_BAND3_FREQUENCY
+MENUITEM_FUNCTION_DYNTEXT(hw_eq_band3_frequency, MENU_FUNC_USEPARAM,
+ hw_eq_do_band_setting,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND3, AUDIOHW_EQ_FREQUENCY),
+ hw_eq_get_name, hw_eq_speak_item,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND3, AUDIOHW_EQ_FREQUENCY),
+ NULL, Icon_NOICON);
+#endif
+#ifdef AUDIOHW_HAVE_EQ_BAND3_WIDTH
+MENUITEM_FUNCTION_DYNTEXT(hw_eq_band3_width, MENU_FUNC_USEPARAM,
+ hw_eq_do_band_setting,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND3, AUDIOHW_EQ_WIDTH),
+ hw_eq_get_name, hw_eq_speak_item,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND3, AUDIOHW_EQ_WIDTH),
+ NULL, Icon_NOICON);
+#endif
+#endif /* AUDIOHW_HAVE_EQ_BAND3 */
+#ifdef AUDIOHW_HAVE_EQ_BAND4
+MENUITEM_FUNCTION_DYNTEXT(hw_eq_band4_gain, MENU_FUNC_USEPARAM,
+ hw_eq_do_band_setting,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND4, AUDIOHW_EQ_GAIN),
+ hw_eq_get_name, hw_eq_speak_item,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND4, AUDIOHW_EQ_GAIN),
+ NULL, Icon_Menu_setting);
+#ifdef AUDIOHW_HAVE_EQ_BAND4_FREQUENCY
+MENUITEM_FUNCTION_DYNTEXT(hw_eq_band4_frequency, MENU_FUNC_USEPARAM,
+ hw_eq_do_band_setting,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND4, AUDIOHW_EQ_FREQUENCY),
+ hw_eq_get_name, hw_eq_speak_item,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND4, AUDIOHW_EQ_FREQUENCY),
+ NULL, Icon_NOICON);
+#endif
+#ifdef AUDIOHW_HAVE_EQ_BAND4_WIDTH
+MENUITEM_FUNCTION_DYNTEXT(hw_eq_band4_width, MENU_FUNC_USEPARAM,
+ hw_eq_do_band_setting,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND4, AUDIOHW_EQ_WIDTH),
+ hw_eq_get_name, hw_eq_speak_item,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND4, AUDIOHW_EQ_WIDTH),
+ NULL, Icon_NOICON);
+#endif
+#endif /* AUDIOHW_HAVE_EQ_BAND4 */
+#ifdef AUDIOHW_HAVE_EQ_BAND5
+MENUITEM_FUNCTION_DYNTEXT(hw_eq_band5_gain, MENU_FUNC_USEPARAM,
+ hw_eq_do_band_setting,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND5, AUDIOHW_EQ_GAIN),
+ hw_eq_get_name, hw_eq_speak_item,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND5, AUDIOHW_EQ_GAIN),
+ NULL, Icon_Menu_setting);
+#ifdef AUDIOHW_HAVE_EQ_BAND5_FREQUENCY
+MENUITEM_FUNCTION_DYNTEXT(hw_eq_band5_frequency, MENU_FUNC_USEPARAM,
+ hw_eq_do_band_setting,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND5, AUDIOHW_EQ_FREQUENCY),
+ hw_eq_get_name, hw_eq_speak_item,
+ HW_EQ_IDX(AUDIOHW_EQ_BAND5, AUDIOHW_EQ_FREQUENCY),
+ NULL, Icon_NOICON);
+#endif
+#endif /* AUDIOHW_HAVE_EQ_BAND5 */
+
+/* Submenu for multiple "tone controls". Gain + all advanced settings. */
+MAKE_MENU(hardware_eq_tone_controls_advanced, ID2P(LANG_HW_EQ_TONE_CONTROLS_ADVANCED),
+ NULL, Icon_NOICON
+ ,&hw_eq_band1_gain
+#ifdef AUDIOHW_HAVE_EQ_BAND1_FREQUENCY
+ ,&hw_eq_band1_frequency
+#endif
+#ifdef AUDIOHW_HAVE_EQ_BAND2
+ ,&hw_eq_band2_gain
+#ifdef AUDIOHW_HAVE_EQ_BAND2_FREQUENCY
+ ,&hw_eq_band2_frequency
+#endif
+#ifdef AUDIOHW_HAVE_EQ_BAND2_WIDTH
+ ,&hw_eq_band2_width
+#endif
+#endif /* AUDIOHW_HAVE_EQ_BAND2 */
+#ifdef AUDIOHW_HAVE_EQ_BAND3
+ ,&hw_eq_band3_gain
+#ifdef AUDIOHW_HAVE_EQ_BAND3_FREQUENCY
+ ,&hw_eq_band3_frequency
+#endif
+#ifdef AUDIOHW_HAVE_EQ_BAND3_WIDTH
+ ,&hw_eq_band3_width
+#endif
+#endif /* AUDIOHW_HAVE_EQ_BAND3 */
+#ifdef AUDIOHW_HAVE_EQ_BAND4
+ ,&hw_eq_band4_gain
+#ifdef AUDIOHW_HAVE_EQ_BAND4_FREQUENCY
+ ,&hw_eq_band4_frequency
+#endif
+#ifdef AUDIOHW_HAVE_EQ_BAND4_WIDTH
+ ,&hw_eq_band4_width
+#endif
+#endif /* AUDIOHW_HAVE_EQ_BAND4 */
+#ifdef AUDIOHW_HAVE_EQ_BAND5
+ ,&hw_eq_band5_gain
+#ifdef AUDIOHW_HAVE_EQ_BAND5_FREQUENCY
+ ,&hw_eq_band5_frequency
+#endif
+#endif /* AUDIOHW_HAVE_EQ_BAND5 */
+ );
+/* Shows only the gains + advanced settings submenu */
+MAKE_MENU(audiohw_eq_tone_controls, ID2P(LANG_HW_EQ_TONE_CONTROLS),
+ NULL, Icon_NOICON
+ ,&hw_eq_band1_gain
+#ifdef AUDIOHW_HAVE_EQ_BAND2
+ ,&hw_eq_band2_gain
+#endif
+#ifdef AUDIOHW_HAVE_EQ_BAND3
+ ,&hw_eq_band3_gain
+#endif
+#ifdef AUDIOHW_HAVE_EQ_BAND4
+ ,&hw_eq_band4_gain
+#endif
+#ifdef AUDIOHW_HAVE_EQ_BAND5
+ ,&hw_eq_band5_gain
+#endif
+ ,&hardware_eq_tone_controls_advanced
+ );
+
diff --git a/apps/menus/exported_menus.h b/apps/menus/exported_menus.h
index 9fb39cbf8f..37b5ff31d0 100644
--- a/apps/menus/exported_menus.h
+++ b/apps/menus/exported_menus.h
@@ -40,6 +40,9 @@ extern const struct menu_item_ex
playlist_settings, /* playlist_menu.c */
playlist_options, /* playlist_menu.c */
equalizer_menu, /* eq_menu.c */
+#ifdef AUDIOHW_HAVE_EQ
+ audiohw_eq_tone_controls, /* audiohw_eq_menu.c */
+#endif
info_menu, /* info_menu.c */
theme_menu; /* theme_menu.c */
diff --git a/apps/menus/sound_menu.c b/apps/menus/sound_menu.c
index 0ce860cb7c..066b1dabae 100644
--- a/apps/menus/sound_menu.c
+++ b/apps/menus/sound_menu.c
@@ -23,6 +23,7 @@
#include <stddef.h>
#include <limits.h>
#include "config.h"
+#include "sound.h"
#include "lang.h"
#include "action.h"
#include "settings.h"
@@ -38,6 +39,7 @@
/***********************************/
/* SOUND MENU */
MENUITEM_SETTING(volume, &global_settings.volume, NULL);
+#ifdef AUDIOHW_HAVE_BASS
MENUITEM_SETTING(bass, &global_settings.bass,
#ifdef HAVE_SW_TONE_CONTROLS
lowlatency_callback
@@ -45,9 +47,14 @@ MENUITEM_SETTING(bass, &global_settings.bass,
NULL
#endif
);
-#ifdef HAVE_WM8758
-MENUITEM_SETTING(bass_cutoff, &global_settings.bass_cutoff, NULL);
+
+#ifdef AUDIOHW_HAVE_BASS_CUTOFF
+MENUITEM_SETTING(treble_cutoff, &global_settings.treble_cutoff, NULL);
#endif
+#endif /* AUDIOHW_HAVE_BASS */
+
+
+#ifdef AUDIOHW_HAVE_TREBLE
MENUITEM_SETTING(treble, &global_settings.treble,
#ifdef HAVE_SW_TONE_CONTROLS
lowlatency_callback
@@ -55,9 +62,13 @@ MENUITEM_SETTING(treble, &global_settings.treble,
NULL
#endif
);
-#ifdef HAVE_WM8758
+
+#ifdef AUDIOHW_HAVE_TREBLE_CUTOFF
MENUITEM_SETTING(treble_cutoff, &global_settings.treble_cutoff, NULL);
#endif
+#endif /* AUDIOHW_HAVE_TREBLE */
+
+
MENUITEM_SETTING(balance, &global_settings.balance, NULL);
MENUITEM_SETTING(channel_config, &global_settings.channel_config,
#if CONFIG_CODEC == SWCODEC
@@ -74,6 +85,10 @@ MENUITEM_SETTING(stereo_width, &global_settings.stereo_width,
#endif
);
+#ifdef AUDIOHW_HAVE_DEPTH_3D
+MENUITEM_SETTING(depth_3d, &global_settings.depth_3d, NULL);
+#endif
+
#if CONFIG_CODEC == SWCODEC
/* Crossfeed Submenu */
MENUITEM_SETTING(crossfeed, &global_settings.crossfeed, lowlatency_callback);
@@ -137,19 +152,30 @@ static int timestretch_callback(int action,const struct menu_item_ex *this_item)
MENUITEM_SETTING(speaker_enabled, &global_settings.speaker_enabled, NULL);
#endif
-
+#ifdef AUDIOHW_HAVE_EQ
+#endif /* AUDIOHW_HAVE_EQ */
MAKE_MENU(sound_settings, ID2P(LANG_SOUND_SETTINGS), NULL, Icon_Audio,
- &volume,
- &bass,
-#ifdef HAVE_WM8758
- &bass_cutoff,
+ &volume
+#ifdef AUDIOHW_HAVE_BASS
+ ,&bass
+#endif
+#ifdef AUDIOHW_HAVE_BASS_CUTOFF
+ ,&bass_cutoff
+#endif
+#ifdef AUDIOHW_HAVE_TREBLE
+ ,&treble
+#endif
+#ifdef AUDIOHW_HAVE_TREBLE_CUTOFF
+ ,&treble_cutoff
+#endif
+#ifdef AUDIOHW_HAVE_EQ
+ ,&audiohw_eq_tone_controls
#endif
- &treble,
-#ifdef HAVE_WM8758
- &treble_cutoff,
+ ,&balance,&channel_config,&stereo_width
+#ifdef AUDIOHW_HAVE_DEPTH_3D
+ ,&depth_3d
#endif
- &balance,&channel_config,&stereo_width
#if CONFIG_CODEC == SWCODEC
,&crossfeed_menu, &equalizer_menu, &dithering_enabled
,&timestretch_enabled
diff --git a/apps/plugin.c b/apps/plugin.c
index b60e2d6768..90380a0039 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -721,6 +721,9 @@ static const struct plugin_api rockbox_api = {
round_value_to_list32,
#endif
+#ifdef AUDIOHW_HAVE_EQ
+ sound_enum_hw_eq_band_setting,
+#endif
};
int plugin_load(const char* plugin, const void* parameter)
diff --git a/apps/plugin.h b/apps/plugin.h
index 5aaa6380b7..108a283596 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -142,7 +142,7 @@ void* plugin_get_buffer(size_t *buffer_size);
#define PLUGIN_MAGIC 0x526F634B /* RocK */
/* increase this every time the api struct changes */
-#define PLUGIN_API_VERSION 184
+#define PLUGIN_API_VERSION 185
/* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any
@@ -884,6 +884,11 @@ int (*round_value_to_list32)(unsigned long value,
int count,
bool signd);
#endif
+
+#ifdef AUDIOHW_HAVE_EQ
+ int (*sound_enum_hw_eq_band_setting)(unsigned int band,
+ unsigned int band_setting);
+#endif /* AUDIOHW_HAVE_EQ */
};
/* plugin header */
diff --git a/apps/plugins/mpegplayer/mpeg_settings.c b/apps/plugins/mpegplayer/mpeg_settings.c
index 6c8a2b8e3e..1ac2476b25 100644
--- a/apps/plugins/mpegplayer/mpeg_settings.c
+++ b/apps/plugins/mpegplayer/mpeg_settings.c
@@ -403,18 +403,53 @@ static void sync_audio_setting(int setting, bool global)
switch (setting)
{
case MPEG_AUDIO_TONE_CONTROLS:
+ #if defined(AUDIOHW_HAVE_BASS) || defined(AUDIOHW_HAVE_TREBLE)
if (global || settings.tone_controls)
{
+ #ifdef AUDIOHW_HAVE_BASS
val0 = rb->global_settings->bass;
+ #endif
+ #ifdef AUDIOHW_HAVE_TREBLE
val1 = rb->global_settings->treble;
+ #endif
}
else
{
+ #ifdef AUDIOHW_HAVE_BASS
val0 = rb->sound_default(SOUND_BASS);
+ #endif
+ #ifdef AUDIOHW_HAVE_TREBLE
val1 = rb->sound_default(SOUND_TREBLE);
+ #endif
}
+ #ifdef AUDIOHW_HAVE_BASS
rb->sound_set(SOUND_BASS, val0);
+ #endif
+ #ifdef AUDIOHW_HAVE_TREBLE
rb->sound_set(SOUND_TREBLE, val1);
+ #endif
+ #endif /* AUDIOHW_HAVE_BASS || AUDIOHW_HAVE_TREBLE */
+
+ #ifdef AUDIOHW_HAVE_EQ
+ for (val1 = 0;; val1++)
+ {
+ int setting = rb->sound_enum_hw_eq_band_setting(val1, AUDIOHW_EQ_GAIN);
+
+ if (setting == -1)
+ break;
+
+ if (global || settings.tone_controls)
+ {
+ val0 = rb->global_settings->hw_eq_bands[val1].gain;
+ }
+ else
+ {
+ val0 = rb->sound_default(setting);
+ }
+
+ rb->sound_set(setting, val0);
+ }
+ #endif /* AUDIOHW_HAVE_EQ */
break;
case MPEG_AUDIO_CHANNEL_MODES:
diff --git a/apps/settings.c b/apps/settings.c
index 4901957263..6349372326 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -27,6 +27,7 @@
#include "config.h"
#include "action.h"
#include "crc32.h"
+#include "sound.h"
#include "settings.h"
#include "debug.h"
#include "usb.h"
@@ -55,7 +56,6 @@
#include "powermgmt.h"
#include "keyboard.h"
#include "version.h"
-#include "sound.h"
#include "rbunicode.h"
#include "dircache.h"
#include "splash.h"
@@ -718,8 +718,12 @@ void sound_settings_apply(void)
#if CONFIG_CODEC == SWCODEC
sound_set_dsp_callback(dsp_callback);
#endif
+#ifdef AUDIOHW_HAVE_BASS
sound_set(SOUND_BASS, global_settings.bass);
+#endif
+#ifdef AUDIOHW_HAVE_TREBLE
sound_set(SOUND_TREBLE, global_settings.treble);
+#endif
sound_set(SOUND_BALANCE, global_settings.balance);
sound_set(SOUND_VOLUME, global_settings.volume);
sound_set(SOUND_CHANNELS, global_settings.channel_config);
@@ -734,13 +738,36 @@ void sound_settings_apply(void)
sound_set(SOUND_MDB_ENABLE, global_settings.mdb_enable);
sound_set(SOUND_SUPERBASS, global_settings.superbass);
#endif
-
-#ifdef HAVE_WM8758
+#ifdef AUDIOHW_HAVE_BASS_CUTOFF
sound_set(SOUND_BASS_CUTOFF, global_settings.bass_cutoff);
+#endif
+#ifdef AUDIOHW_HAVE_TREBLE_CUTOFF
sound_set(SOUND_TREBLE_CUTOFF, global_settings.treble_cutoff);
#endif
-}
+#ifdef AUDIOHW_HAVE_DEPTH_3D
+ sound_set(SOUND_DEPTH_3D, global_settings.depth_3d);
+#endif
+#ifdef AUDIOHW_HAVE_EQ
+ int b;
+ for (b = 0; b < AUDIOHW_EQ_BAND_NUM; b++)
+ {
+ int setting = sound_enum_hw_eq_band_setting(b, AUDIOHW_EQ_GAIN);
+ sound_set(setting, global_settings.hw_eq_bands[b].gain);
+
+#ifdef AUDIOHW_HAVE_EQ_FREQUENCY
+ setting = sound_enum_hw_eq_band_setting(b, AUDIOHW_EQ_FREQUENCY);
+ if (setting != -1)
+ sound_set(setting, global_settings.hw_eq_bands[b].frequency);
+#endif /* AUDIOHW_HAVE_EQ_FREQUENCY */
+#ifdef AUDIOHW_HAVE_EQ_WIDTH
+ setting = sound_enum_hw_eq_band_setting(b, AUDIOHW_EQ_WIDTH);
+ if (setting != -1)
+ sound_set(setting, global_settings.hw_eq_bands[b].width);
+#endif /* AUDIOHW_HAVE_EQ_WIDTH */
+ }
+#endif
+}
void settings_apply(bool read_disk)
{
diff --git a/apps/settings.h b/apps/settings.h
index 2fdff9918a..c8e8d642a2 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -336,7 +336,7 @@ struct user_settings
bool superbass; /* true/false */
#endif
-#ifdef HAVE_WM8758
+#if defined(HAVE_WM8758) || defined(HAVE_WM8978)
int bass_cutoff;
int treble_cutoff;
#endif
@@ -831,6 +831,25 @@ struct user_settings
/* When resuming playback (after a stop), rewind this number of seconds */
int resume_rewind;
#endif
+
+#ifdef AUDIOHW_HAVE_DEPTH_3D
+ int depth_3d;
+#endif
+
+#ifdef AUDIOHW_HAVE_EQ
+ /** Hardware EQ tone controls **/
+ struct hw_eq_band
+ {
+ /* Maintain the order of members or sound_menu has to be changed */
+ int gain;
+#ifdef AUDIOHW_HAVE_EQ_FREQUENCY
+ int frequency;
+#endif
+#ifdef AUDIOHW_HAVE_EQ_WIDTH
+ int width;
+#endif
+ } hw_eq_bands[AUDIOHW_EQ_BAND_NUM];
+#endif /* AUDIOHW_HAVE_EQ */
};
/** global variables **/
diff --git a/apps/settings_list.c b/apps/settings_list.c
index 1bc783219f..d6f5f94f66 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -29,10 +29,10 @@
#include "lcd.h"
#include "button.h"
#include "backlight.h"
+#include "sound.h"
#include "settings.h"
#include "settings_list.h"
#include "usb.h"
-#include "sound.h"
#include "dsp.h"
#include "audio.h"
#include "power.h"
@@ -552,9 +552,97 @@ const struct settings_list settings[] = {
/* sound settings */
SOUND_SETTING(F_NO_WRAP,volume, LANG_VOLUME, "volume", SOUND_VOLUME),
SOUND_SETTING(0, balance, LANG_BALANCE, "balance", SOUND_BALANCE),
+/* Tone controls */
+#ifdef AUDIOHW_HAVE_BASS
SOUND_SETTING(F_NO_WRAP,bass, LANG_BASS, "bass", SOUND_BASS),
+#endif
+#ifdef AUDIOHW_HAVE_TREBLE
SOUND_SETTING(F_NO_WRAP,treble, LANG_TREBLE, "treble", SOUND_TREBLE),
-
+#endif
+/* Hardware EQ tone controls */
+#ifdef AUDIOHW_HAVE_EQ
+/* Band gain is generic */
+ SOUND_SETTING(F_NO_WRAP, hw_eq_bands[AUDIOHW_EQ_BAND1].gain,
+ LANG_HW_EQ_GAIN, "tone band1 gain", SOUND_EQ_BAND1_GAIN),
+#ifdef AUDIOHW_HAVE_EQ_BAND2
+ SOUND_SETTING(F_NO_WRAP, hw_eq_bands[AUDIOHW_EQ_BAND2].gain,
+ LANG_HW_EQ_GAIN, "tone band2 gain", SOUND_EQ_BAND2_GAIN),
+#endif /* AUDIOHW_HAVE_EQ_BAND2 */
+#ifdef AUDIOHW_HAVE_EQ_BAND3
+ SOUND_SETTING(F_NO_WRAP, hw_eq_bands[AUDIOHW_EQ_BAND3].gain,
+ LANG_HW_EQ_GAIN, "tone band3 gain", SOUND_EQ_BAND3_GAIN),
+#endif /* AUDIOHW_HAVE_EQ_BAND3 */
+#ifdef AUDIOHW_HAVE_EQ_BAND4
+ SOUND_SETTING(F_NO_WRAP, hw_eq_bands[AUDIOHW_EQ_BAND4].gain,
+ LANG_HW_EQ_GAIN, "tone band4 gain", SOUND_EQ_BAND4_GAIN),
+#endif /* AUDIOHW_HAVE_EQ_BAND4 */
+#ifdef AUDIOHW_HAVE_EQ_BAND5
+ SOUND_SETTING(F_NO_WRAP, hw_eq_bands[AUDIOHW_EQ_BAND5].gain,
+ LANG_HW_EQ_GAIN, "tone band5 gain", SOUND_EQ_BAND5_GAIN),
+#endif /* AUDIOHW_HAVE_EQ_BAND5 */
+#ifdef HAVE_WM8978
+ /* Frequencies vary with samplerate but at least the user has an idea
+ * about the bands and it will be correct with normal playback rates. */
+/* Band 1 */
+ STRINGCHOICE_SETTING(F_SOUNDSETTING,
+ hw_eq_bands[AUDIOHW_EQ_BAND1].frequency,
+ LANG_HW_EQ_FREQUENCY, 0,"tone band1 frequency",
+ "80 Hz,105 Hz,135 Hz,175 Hz",
+ sound_set_hw_eq_band1_frequency, 4,
+ TALK_ID(80, UNIT_HERTZ), TALK_ID(105, UNIT_HERTZ),
+ TALK_ID(135, UNIT_HERTZ), TALK_ID(175, UNIT_HERTZ)),
+/* Band 2 */
+ STRINGCHOICE_SETTING(F_SOUNDSETTING,
+ hw_eq_bands[AUDIOHW_EQ_BAND2].frequency,
+ LANG_HW_EQ_FREQUENCY, 0,"tone band2 frequency",
+ "230 Hz,300 Hz,385 Hz,500 Hz",
+ sound_set_hw_eq_band2_frequency, 4,
+ TALK_ID(230, UNIT_HERTZ), TALK_ID(300, UNIT_HERTZ),
+ TALK_ID(385, UNIT_HERTZ), TALK_ID(500, UNIT_HERTZ)),
+ CHOICE_SETTING(F_SOUNDSETTING, hw_eq_bands[AUDIOHW_EQ_BAND2].width,
+ LANG_HW_EQ_WIDTH, 0, "tone band2 width", "narrow,wide",
+ sound_set_hw_eq_band2_width, 2,
+ ID2P(LANG_HW_EQ_WIDTH_NARROW), ID2P(LANG_HW_EQ_WIDTH_WIDE)),
+/* Band 3 */
+ STRINGCHOICE_SETTING(F_SOUNDSETTING,
+ hw_eq_bands[AUDIOHW_EQ_BAND3].frequency,
+ LANG_HW_EQ_FREQUENCY, 0, "tone band3 frequency",
+ "650 Hz,850 Hz,1.1 kHz,1.4 kHz",
+ sound_set_hw_eq_band3_frequency, 4,
+ TALK_ID(650, UNIT_HERTZ), TALK_ID(850, UNIT_HERTZ),
+ TALK_ID_DECIMAL(11, 1, UNIT_KHZ),
+ TALK_ID_DECIMAL(14, 1, UNIT_KHZ)),
+ CHOICE_SETTING(F_SOUNDSETTING,hw_eq_bands[AUDIOHW_EQ_BAND3].width,
+ LANG_HW_EQ_WIDTH, 0, "tone band3 width", "narrow,wide",
+ sound_set_hw_eq_band3_width, 2,
+ ID2P(LANG_HW_EQ_WIDTH_NARROW), ID2P(LANG_HW_EQ_WIDTH_WIDE)),
+/* Band 4 */
+ STRINGCHOICE_SETTING(F_SOUNDSETTING,
+ hw_eq_bands[AUDIOHW_EQ_BAND4].frequency,
+ LANG_HW_EQ_FREQUENCY, 0, "tone band4 frequency",
+ "1.8 kHz,2.4 kHz,3.2 kHz,4.1 kHz",
+ sound_set_hw_eq_band4_frequency, 4,
+ TALK_ID_DECIMAL(18, 1, UNIT_KHZ),
+ TALK_ID_DECIMAL(24, 1, UNIT_KHZ),
+ TALK_ID_DECIMAL(32, 1, UNIT_KHZ),
+ TALK_ID_DECIMAL(41, 1, UNIT_KHZ)),
+ CHOICE_SETTING(F_SOUNDSETTING, hw_eq_bands[AUDIOHW_EQ_BAND4].width,
+ LANG_HW_EQ_WIDTH, 0, "tone band4 width", "narrow,wide",
+ sound_set_hw_eq_band4_width, 2,
+ ID2P(LANG_HW_EQ_WIDTH_NARROW), ID2P(LANG_HW_EQ_WIDTH_WIDE)),
+/* Band 5 */
+ STRINGCHOICE_SETTING(F_SOUNDSETTING,
+ hw_eq_bands[AUDIOHW_EQ_BAND5].frequency,
+ LANG_HW_EQ_FREQUENCY, 0, "tone band5 frequency",
+ "5.3 kHz,6.9 kHz,9.0 kHz,11.7 kHz",
+ sound_set_hw_eq_band5_frequency, 4,
+ TALK_ID_DECIMAL(53, 1, UNIT_KHZ),
+ TALK_ID_DECIMAL(69, 1, UNIT_KHZ),
+ TALK_ID_DECIMAL(90, 1, UNIT_KHZ),
+ TALK_ID_DECIMAL(117, 1, UNIT_KHZ)),
+#endif /* HAVE_WM8978 */
+#endif /* AUDIOHW_HAVE_EQ */
+/* 3-d enhancement effect */
#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
SOUND_SETTING(0,loudness, LANG_LOUDNESS, "loudness", SOUND_LOUDNESS),
STRINGCHOICE_SETTING(F_SOUNDSETTING,avc,LANG_AUTOVOL,0,"auto volume",
@@ -574,6 +662,10 @@ const struct settings_list settings[] = {
ID2P(LANG_CHANNEL_RIGHT), ID2P(LANG_CHANNEL_KARAOKE)),
SOUND_SETTING(F_SOUNDSETTING, stereo_width, LANG_STEREO_WIDTH,
"stereo_width", SOUND_STEREO_WIDTH),
+#ifdef AUDIOHW_HAVE_DEPTH_3D
+ SOUND_SETTING(0,depth_3d, LANG_DEPTH_3D, "3-d enhancement",
+ SOUND_DEPTH_3D),
+#endif
/* playback */
OFFON_SETTING(0, playlist_shuffle, LANG_SHUFFLE, false, "shuffle", NULL),
SYSTEM_SETTING(NVRAM(4), resume_index, -1),
@@ -1332,9 +1424,11 @@ const struct settings_list settings[] = {
"compressor release time", UNIT_MS, 100, 1000,
100, NULL, NULL, compressor_set),
#endif
-#ifdef HAVE_WM8758
+#ifdef AUDIOHW_HAVE_BASS_CUTOFF
SOUND_SETTING(F_NO_WRAP, bass_cutoff, LANG_BASS_CUTOFF,
"bass cutoff", SOUND_BASS_CUTOFF),
+#endif
+#ifdef AUDIOHW_HAVE_TREBLE_CUTOFF
SOUND_SETTING(F_NO_WRAP, treble_cutoff, LANG_TREBLE_CUTOFF,
"treble cutoff", SOUND_TREBLE_CUTOFF),
#endif
diff --git a/firmware/drivers/audio/wm8978.c b/firmware/drivers/audio/wm8978.c
index a2dbf5a8fb..2d57ce3f10 100644
--- a/firmware/drivers/audio/wm8978.c
+++ b/firmware/drivers/audio/wm8978.c
@@ -37,27 +37,35 @@ extern void audiohw_enable_headphone_jack(bool enable);
const struct sound_settings_info audiohw_settings[] =
{
- [SOUND_VOLUME] = {"dB", 0, 1, -90, 6, -25},
- [SOUND_BASS] = {"dB", 0, 1, -12, 12, 0},
- [SOUND_TREBLE] = {"dB", 0, 1, -12, 12, 0},
- [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0},
- [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0},
- [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100},
+ [SOUND_VOLUME] = {"dB", 0, 1, -90, 6, -25},
+ [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0},
+ [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0},
+ [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100},
+ [SOUND_EQ_BAND1_GAIN] = {"dB", 0, 1, -12, 12, 0},
+ [SOUND_EQ_BAND2_GAIN] = {"dB", 0, 1, -12, 12, 0},
+ [SOUND_EQ_BAND3_GAIN] = {"dB", 0, 1, -12, 12, 0},
+ [SOUND_EQ_BAND4_GAIN] = {"dB", 0, 1, -12, 12, 0},
+ [SOUND_EQ_BAND5_GAIN] = {"dB", 0, 1, -12, 12, 0},
+ [SOUND_EQ_BAND1_FREQUENCY] = {"", 0, 1, 0, 3, 0},
+ [SOUND_EQ_BAND2_FREQUENCY] = {"", 0, 1, 0, 3, 0},
+ [SOUND_EQ_BAND3_FREQUENCY] = {"", 0, 1, 0, 3, 0},
+ [SOUND_EQ_BAND4_FREQUENCY] = {"", 0, 1, 0, 3, 0},
+ [SOUND_EQ_BAND5_FREQUENCY] = {"", 0, 1, 0, 3, 0},
+ [SOUND_EQ_BAND2_WIDTH] = {"", 0, 1, 0, 1, 0},
+ [SOUND_EQ_BAND3_WIDTH] = {"", 0, 1, 0, 1, 0},
+ [SOUND_EQ_BAND4_WIDTH] = {"", 0, 1, 0, 1, 0},
+ [SOUND_DEPTH_3D] = {"%", 0, 1, 0, 15, 0},
#ifdef HAVE_RECORDING
/* Digital: -119.0dB to +8.0dB in 0.5dB increments
* Analog: Relegated to volume control
* Circumstances unfortunately do not allow a great deal of positive
* gain. */
- [SOUND_LEFT_GAIN] = {"dB", 1, 1,-238, 16, 0},
- [SOUND_RIGHT_GAIN] = {"dB", 1, 1,-238, 16, 0},
+ [SOUND_LEFT_GAIN] = {"dB", 1, 1,-238, 16, 0},
+ [SOUND_RIGHT_GAIN] = {"dB", 1, 1,-238, 16, 0},
#if 0
- [SOUND_MIC_GAIN] = {"dB", 1, 1,-238, 16, 0},
+ [SOUND_MIC_GAIN] = {"dB", 1, 1,-238, 16, 0},
#endif
#endif
-#if 0
- [SOUND_BASS_CUTOFF] = {"", 0, 1, 1, 4, 1},
- [SOUND_TREBLE_CUTOFF] = {"", 0, 1, 1, 4, 1},
-#endif
};
static uint16_t wmc_regs[WMC_NUM_REGISTERS] =
@@ -123,10 +131,20 @@ struct
{
int vol_l;
int vol_r;
+ int dac_l;
+ int dac_r;
bool ahw_mute;
+ int prescaler;
+ int enhance_3d_prescaler;
} wmc_vol =
{
- 0, 0, false
+ .vol_l = 0,
+ .vol_r = 0,
+ .dac_l = 0,
+ .dac_r = 0,
+ .ahw_mute = false,
+ .prescaler = 0,
+ .enhance_3d_prescaler = 0,
};
static void wmc_write(unsigned int reg, unsigned int val)
@@ -191,6 +209,10 @@ int sound_val2phys(int setting, int value)
break;
#endif
+ case SOUND_DEPTH_3D:
+ result = (100 * value + 8) / 15;
+ break;
+
default:
result = value;
}
@@ -216,8 +238,12 @@ void audiohw_preinit(void)
wmc_set(WMC_OUT4_MONO_MIXER_CTRL, WMC_MUTE);
/* 3. Set L/RMIXEN = 1 and DACENL/R = 1 in register R3. */
- wmc_write(WMC_POWER_MANAGEMENT3,
- WMC_RMIXEN | WMC_LMIXEN | WMC_DACENR | WMC_DACENL);
+ wmc_write(WMC_POWER_MANAGEMENT3, WMC_RMIXEN | WMC_LMIXEN);
+
+ /* EQ and 3D applied to DAC (Set before DAC enable!) */
+ wmc_set(WMC_EQ1_LOW_SHELF, WMC_EQ3DMODE);
+
+ wmc_set(WMC_POWER_MANAGEMENT3, WMC_DACENR | WMC_DACENL);
/* 4. Set BUFIOEN = 1 and VMIDSEL[1:0] to required value in register
* R1. Wait for VMID supply to settle */
@@ -305,6 +331,12 @@ void audiohw_set_headphone_vol(int vol_l, int vol_r)
get_headphone_levels(vol_l, &dac_l, &hp_l, &mix_l, &boost_l);
get_headphone_levels(vol_r, &dac_r, &hp_r, &mix_r, &boost_r);
+ wmc_vol.dac_l = dac_l;
+ wmc_vol.dac_r = dac_r;
+
+ dac_l -= wmc_vol.prescaler + wmc_vol.enhance_3d_prescaler;
+ dac_r -= wmc_vol.prescaler + wmc_vol.enhance_3d_prescaler;
+
wmc_write_masked(WMC_LEFT_MIXER_CTRL, mix_l << WMC_BYPLMIXVOL_POS,
WMC_BYPLMIXVOL);
wmc_write_masked(WMC_LEFT_ADC_BOOST_CTRL,
@@ -367,6 +399,64 @@ static void audiohw_mute(bool mute)
}
}
+/* Equalizer - set the eq band level -12 to +12 dB. */
+void audiohw_set_eq_band_gain(unsigned int band, int val)
+{
+ if (band > 4)
+ return;
+
+ wmc_write_masked(band + WMC_EQ1_LOW_SHELF, 12 - val, WMC_EQG);
+}
+
+/* Equalizer - set the eq band frequency index. */
+void audiohw_set_eq_band_frequency(unsigned int band, int val)
+{
+ if (band > 4)
+ return;
+
+ wmc_write_masked(band + WMC_EQ1_LOW_SHELF,
+ val << WMC_EQC_POS, WMC_EQC);
+}
+
+/* Equalizer - set bandwidth for peaking filters to wide (!= 0) or
+ * narrow (0); only valid for peaking filter bands 1-3. */
+void audiohw_set_eq_band_width(unsigned int band, int val)
+{
+ if (band < 1 || band > 3)
+ return;
+
+ wmc_write_masked(band + WMC_EQ1_LOW_SHELF,
+ (val == 0) ? 0 : WMC_EQBW, WMC_EQBW);
+}
+
+/* Set prescaler to prevent clipping the output amp when applying positive
+ * gain to EQ bands. */
+void audiohw_set_prescaler(int val)
+{
+ val *= 2;
+ wmc_vol.prescaler = val;
+ val += wmc_vol.enhance_3d_prescaler; /* Combine with 3D attenuation */
+
+ wmc_write_masked(WMC_LEFT_DAC_DIGITAL_VOL, wmc_vol.dac_l - val,
+ WMC_DVOL);
+ wmc_write_masked(WMC_RIGHT_DAC_DIGITAL_VOL, wmc_vol.dac_r - val,
+ WMC_DVOL);
+}
+
+/* Set the depth of the 3D effect */
+void audiohw_set_depth_3d(int val)
+{
+ int att = 10*val / 15; /* -5 dB @ full setting */
+ wmc_vol.enhance_3d_prescaler = att;
+ att += wmc_vol.prescaler; /* Combine with prescaler attenuation */
+
+ wmc_write_masked(WMC_LEFT_DAC_DIGITAL_VOL, wmc_vol.dac_l - att,
+ WMC_DVOL);
+ wmc_write_masked(WMC_RIGHT_DAC_DIGITAL_VOL, wmc_vol.dac_r - att,
+ WMC_DVOL);
+ wmc_write_masked(WMC_3D_CONTROL, val, WMC_DEPTH3D);
+}
+
void audiohw_close(void)
{
/* 1. Mute all analogue outputs */
diff --git a/firmware/export/audiohw.h b/firmware/export/audiohw.h
index 22f6e68562..12c4738f7c 100644
--- a/firmware/export/audiohw.h
+++ b/firmware/export/audiohw.h
@@ -26,13 +26,15 @@
#include <stdbool.h>
/* define some audiohw caps */
-#define TREBLE_CAP (1 << 0)
-#define BASS_CAP (1 << 1)
-#define BALANCE_CAP (1 << 2)
-#define CLIPPING_CAP (1 << 3)
-#define PRESCALER_CAP (1 << 4)
-#define BASS_CUTOFF_CAP (1 << 5)
-#define TREBLE_CUTOFF_CAP (1 << 6)
+#define TREBLE_CAP (1 << 0)
+#define BASS_CAP (1 << 1)
+#define BALANCE_CAP (1 << 2)
+#define CLIPPING_CAP (1 << 3)
+#define PRESCALER_CAP (1 << 4)
+#define BASS_CUTOFF_CAP (1 << 5)
+#define TREBLE_CUTOFF_CAP (1 << 6)
+#define EQ_CAP (1 << 7)
+#define DEPTH_3D_CAP (1 << 8)
#ifdef HAVE_UDA1380
#include "uda1380.h"
@@ -75,12 +77,17 @@
#define VOLUME_MAX 0
#endif
+#ifndef AUDIOHW_NUM_TONE_CONTROLS
+#define AUDIOHW_NUM_TONE_CONTROLS 0
+#endif
+
/* volume/balance/treble/bass interdependency main part */
#define VOLUME_RANGE (VOLUME_MAX - VOLUME_MIN)
/* convert caps into defines */
#ifdef AUDIOHW_CAPS
+/* Tone controls */
#if (AUDIOHW_CAPS & TREBLE_CAP)
#define AUDIOHW_HAVE_TREBLE
#endif
@@ -89,6 +96,14 @@
#define AUDIOHW_HAVE_BASS
#endif
+#if (AUDIOHW_CAPS & BASS_CUTOFF_CAP)
+#define AUDIOHW_HAVE_BASS_CUTOFF
+#endif
+
+#if (AUDIOHW_CAPS & TREBLE_CUTOFF_CAP)
+#define AUDIOHW_HAVE_TREBLE_CUTOFF
+#endif
+
#if (AUDIOHW_CAPS & BALANCE_CAP)
#define AUDIOHW_HAVE_BALANCE
#endif
@@ -101,19 +116,127 @@
#define AUDIOHW_HAVE_PRESCALER
#endif
-#if (AUDIOHW_CAPS & BASS_CUTOFF_CAP)
-#define AUDIOHW_HAVE_BASS_CUTOFF
+/* Hardware EQ tone controls */
+#if (AUDIOHW_CAPS & EQ_CAP)
+/* A hardware equalizer is present (or perhaps some tone control variation
+ * that is not Bass and/or Treble) */
+#define AUDIOHW_HAVE_EQ
+
+/* Defined band indexes for supported bands */
+enum
+{
+ /* Band 1 is implied; bands must be contiguous, 1 to N */
+ AUDIOHW_EQ_BAND1 = 0,
+#define AUDIOHW_HAVE_EQ_BAND1
+#if (AUDIOHW_EQ_BAND_CAPS & (EQ_CAP << 1))
+ AUDIOHW_EQ_BAND2,
+#define AUDIOHW_HAVE_EQ_BAND2
+#if (AUDIOHW_EQ_BAND_CAPS & (EQ_CAP << 2))
+ AUDIOHW_EQ_BAND3,
+#define AUDIOHW_HAVE_EQ_BAND3
+#if (AUDIOHW_EQ_BAND_CAPS & (EQ_CAP << 3))
+ AUDIOHW_EQ_BAND4,
+#define AUDIOHW_HAVE_EQ_BAND4
+#if (AUDIOHW_EQ_BAND_CAPS & (EQ_CAP << 4))
+ AUDIOHW_EQ_BAND5,
+#define AUDIOHW_HAVE_EQ_BAND5
+#endif /* 5 */
+#endif /* 4 */
+#endif /* 3 */
+#endif /* 2 */
+ AUDIOHW_EQ_BAND_NUM, /* Keep last */
+};
+
+#ifdef AUDIOHW_EQ_FREQUENCY_CAPS
+/* One or more bands supports frequency cutoff or center adjustment */
+#define AUDIOHW_HAVE_EQ_FREQUENCY
+enum
+{
+ __AUDIOHW_EQ_BAND_FREQUENCY = -1,
+#if defined(AUDIOHW_HAVE_EQ_BAND1) && \
+ (AUDIOHW_EQ_FREQUENCY_CAPS & (EQ_CAP << 0))
+ AUDIOHW_EQ_BAND1_FREQUENCY,
+#define AUDIOHW_HAVE_EQ_BAND1_FREQUENCY
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND2) && \
+ (AUDIOHW_EQ_FREQUENCY_CAPS & (EQ_CAP << 1))
+ AUDIOHW_EQ_BAND2_FREQUENCY,
+#define AUDIOHW_HAVE_EQ_BAND2_FREQUENCY
#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND3) && \
+ (AUDIOHW_EQ_FREQUENCY_CAPS & (EQ_CAP << 2))
+ AUDIOHW_EQ_BAND3_FREQUENCY,
+#define AUDIOHW_HAVE_EQ_BAND3_FREQUENCY
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND4) && \
+ (AUDIOHW_EQ_FREQUENCY_CAPS & (EQ_CAP << 3))
+ AUDIOHW_EQ_BAND4_FREQUENCY,
+#define AUDIOHW_HAVE_EQ_BAND4_FREQUENCY
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND5) && \
+ (AUDIOHW_EQ_FREQUENCY_CAPS & (EQ_CAP << 4))
+ AUDIOHW_EQ_BAND5_FREQUENCY,
+#define AUDIOHW_HAVE_EQ_BAND5_FREQUENCY
+#endif
+ AUDIOHW_EQ_FREQUENCY_NUM,
+};
+#endif /* AUDIOHW_EQ_FREQUENCY_CAPS */
+
+#ifdef AUDIOHW_EQ_WIDTH_CAPS
+/* One or more bands supports bandwidth adjustment */
+#define AUDIOHW_HAVE_EQ_WIDTH
+enum
+{
+ __AUDIOHW_EQ_BAND_WIDTH = -1,
+#if defined(AUDIOHW_HAVE_EQ_BAND1) && \
+ (AUDIOHW_EQ_WIDTH_CAPS & (EQ_CAP << 1))
+ AUDIOHW_EQ_BAND2_WIDTH,
+#define AUDIOHW_HAVE_EQ_BAND2_WIDTH
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND2) && \
+ (AUDIOHW_EQ_WIDTH_CAPS & (EQ_CAP << 2))
+ AUDIOHW_EQ_BAND3_WIDTH,
+#define AUDIOHW_HAVE_EQ_BAND3_WIDTH
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND3) && \
+ (AUDIOHW_EQ_WIDTH_CAPS & (EQ_CAP << 3))
+ AUDIOHW_EQ_BAND4_WIDTH,
+#define AUDIOHW_HAVE_EQ_BAND4_WIDTH
+#endif
+ AUDIOHW_EQ_WIDTH_NUM, /* Keep last */
+};
+#endif /* AUDIOHW_EQ_WIDTH_CAPS */
+
+/* Types and number of settings types (gain, frequency, width) */
+enum AUDIOHW_EQ_SETTINGS
+{
+ AUDIOHW_EQ_GAIN = 0,
+#ifdef AUDIOHW_HAVE_EQ_FREQUENCY
+ AUDIOHW_EQ_FREQUENCY,
+#endif
+#ifdef AUDIOHW_HAVE_EQ_WIDTH
+ AUDIOHW_EQ_WIDTH,
+#endif
+ AUDIOHW_EQ_SETTING_NUM
+};
-#if (AUDIOHW_CAPS & TREBLE_CUTOFF_CAP)
-#define AUDIOHW_HAVE_TREBLE_CUTOFF
+#endif /* (AUDIOHW_CAPS & EQ_CAP) */
+
+#if (AUDIOHW_CAPS & DEPTH_3D_CAP)
+#define AUDIOHW_HAVE_DEPTH_3D
#endif
+
#endif /* AUDIOHW_CAPS */
enum {
SOUND_VOLUME = 0,
+/* Tone control */
+#if defined(AUDIOHW_HAVE_BASS)
SOUND_BASS,
+#endif
+#if defined(AUDIOHW_HAVE_TREBLE)
SOUND_TREBLE,
+#endif
SOUND_BALANCE,
SOUND_CHANNELS,
SOUND_STEREO_WIDTH,
@@ -132,12 +255,61 @@ enum {
SOUND_RIGHT_GAIN,
SOUND_MIC_GAIN,
#endif
+/* Bass and treble tone controls */
#if defined(AUDIOHW_HAVE_BASS_CUTOFF)
SOUND_BASS_CUTOFF,
#endif
#if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
SOUND_TREBLE_CUTOFF,
#endif
+/* 3D effect */
+#if defined(AUDIOHW_HAVE_DEPTH_3D)
+ SOUND_DEPTH_3D,
+#endif
+/* Hardware EQ tone controls */
+/* Band gains */
+#if defined(AUDIOHW_HAVE_EQ)
+ /* Band 1 implied */
+ SOUND_EQ_BAND1_GAIN,
+#if defined(AUDIOHW_HAVE_EQ_BAND2)
+ SOUND_EQ_BAND2_GAIN,
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND3)
+ SOUND_EQ_BAND3_GAIN,
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND4)
+ SOUND_EQ_BAND4_GAIN,
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND5)
+ SOUND_EQ_BAND5_GAIN,
+#endif
+/* Band frequencies */
+#if defined(AUDIOHW_HAVE_EQ_BAND1_FREQUENCY)
+ SOUND_EQ_BAND1_FREQUENCY,
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND2_FREQUENCY)
+ SOUND_EQ_BAND2_FREQUENCY,
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND3_FREQUENCY)
+ SOUND_EQ_BAND3_FREQUENCY,
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND4_FREQUENCY)
+ SOUND_EQ_BAND4_FREQUENCY,
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND5_FREQUENCY)
+ SOUND_EQ_BAND5_FREQUENCY,
+#endif
+/* Band widths */
+#if defined(AUDIOHW_HAVE_EQ_BAND2_WIDTH)
+ SOUND_EQ_BAND2_WIDTH,
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND3_WIDTH)
+ SOUND_EQ_BAND3_WIDTH,
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND4_WIDTH)
+ SOUND_EQ_BAND4_WIDTH,
+#endif
+#endif /* AUDIOHW_HAVE_EQ */
SOUND_LAST_SETTING, /* Keep this last */
};
@@ -262,6 +434,64 @@ void audiohw_set_bass_cutoff(int val);
void audiohw_set_treble_cutoff(int val);
#endif
+#ifdef AUDIOHW_HAVE_EQ
+/**
+ * Set new band gain value.
+ * @param band index to which val is set
+ * @param val to set.
+ * NOTE: AUDIOHW_CAPS need to contain
+ * EQ_CAP
+ *
+ * AUDIOHW_EQ_BAND_CAPS must be defined as a bitmask
+ * of EQ_CAP each shifted by the zero-based band number
+ * for each band. Bands 1 to N are indexed 0 to N-1.
+ */
+void audiohw_set_eq_band_gain(unsigned int band, int val);
+#endif
+
+#ifdef AUDIOHW_HAVE_EQ_FREQUENCY
+/**
+ * Set new band cutoff or center frequency value.
+ * @param band index to which val is set
+ * @param val to set.
+ * NOTE: AUDIOHW_CAPS need to contain
+ * EQ_CAP
+ *
+ * AUDIOHW_EQ_FREQUENCY_CAPS must be defined as a bitmask
+ * of EQ_CAP each shifted by the zero-based band number
+ * for each band that supports frequency adjustment.
+ * Bands 1 to N are indexed 0 to N-1.
+ */
+void audiohw_set_eq_band_frequency(unsigned int band, int val);
+#endif
+
+#ifdef AUDIOHW_HAVE_EQ_WIDTH
+/**
+ * Set new band cutoff or center frequency value.
+ * @param band index to which val is set
+ * @param val to set.
+ * NOTE: AUDIOHW_CAPS need to contain
+ * EQ_CAP
+ *
+ * AUDIOHW_EQ_WIDTH_CAPS must be defined as a bitmask
+ * of EQ_CAP each shifted by the zero-based band number
+ * for each band that supports width adjustment.
+ * Bands 1 to N are indexed 0 to N-1.
+ */
+void audiohw_set_eq_band_width(unsigned int band, int val);
+#endif
+
+#ifdef AUDIOHW_HAVE_DEPTH_3D
+/**
+ * Set new 3-d enhancement (stereo expansion) effect value.
+ * @param val to set.
+ * NOTE: AUDIOHW_CAPS need to contain
+ * DEPTH_3D_CAP
+ */
+void audiohw_set_depth_3d(int val);
+#endif
+
+
void audiohw_set_frequency(int fsel);
#ifdef HAVE_RECORDING
diff --git a/firmware/export/config/gigabeats.h b/firmware/export/config/gigabeats.h
index 2bc56ec98c..73eb79ce90 100644
--- a/firmware/export/config/gigabeats.h
+++ b/firmware/export/config/gigabeats.h
@@ -90,9 +90,6 @@
/* Define this if you have the WM8978 audio codec */
#define HAVE_WM8978
-/* Tone controls for WM8978 have not been implemented yet */
-#define HAVE_SW_TONE_CONTROLS
-
/* Define bitmask of input sources - recordable bitmask can be defined
explicitly if different */
#define INPUT_SRC_CAPS SRC_CAP_FMRADIO
diff --git a/firmware/export/sound.h b/firmware/export/sound.h
index e68ae23774..7243f48e79 100644
--- a/firmware/export/sound.h
+++ b/firmware/export/sound.h
@@ -55,10 +55,70 @@ void sound_set_bass(int value);
void sound_set_treble(int value);
void sound_set_channels(int value);
void sound_set_stereo_width(int value);
-#if defined(HAVE_WM8758) || defined(HAVE_WM8985)
+#if defined(AUDIOHW_HAVE_BASS_CUTOFF)
void sound_set_bass_cutoff(int value);
+#endif
+#if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
void sound_set_treble_cutoff(int value);
#endif
+
+#if defined(AUDIOHW_HAVE_DEPTH_3D)
+void sound_set_depth_3d(int value);
+#endif
+
+#ifdef AUDIOHW_HAVE_EQ
+/*
+ * band = SOUND_EQ_BANDb
+ * band_setting = AUDIOHW_EQ_s
+ *
+ * Returns SOUND_EQ_BANDb_s or -1 if it doesn't exist.
+ *
+ * b: band number
+ * s: one of GAIN, FREQUENCY, WIDTH
+ */
+int sound_enum_hw_eq_band_setting(unsigned int band,
+ unsigned int band_setting);
+/* Band1 implied */
+void sound_set_hw_eq_band1_gain(int value);
+#ifdef AUDIOHW_HAVE_EQ_BAND1_FREQUENCY
+void sound_set_hw_eq_band1_frequency(int value);
+#endif
+#ifdef AUDIOHW_HAVE_EQ_BAND2
+void sound_set_hw_eq_band2_gain(int value);
+#ifdef AUDIOHW_HAVE_EQ_BAND2_FREQUENCY
+void sound_set_hw_eq_band2_frequency(int value);
+#endif
+#ifdef AUDIOHW_HAVE_EQ_BAND2_WIDTH
+void sound_set_hw_eq_band2_width(int value);
+#endif
+#endif /* AUDIOHW_HAVE_EQ_BAND2 */
+#ifdef AUDIOHW_HAVE_EQ_BAND3
+/* Band 3 */
+void sound_set_hw_eq_band3_gain(int value);
+#ifdef AUDIOHW_HAVE_EQ_BAND3_FREQUENCY
+void sound_set_hw_eq_band3_frequency(int value);
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND3_WIDTH)
+void sound_set_hw_eq_band3_width(int value);
+#endif
+#endif /* AUDIOHW_HAVE_EQ_BAND3 */
+#ifdef AUDIOHW_HAVE_EQ_BAND4
+void sound_set_hw_eq_band4_gain(int value);
+#ifdef AUDIOHW_HAVE_EQ_BAND4_FREQUENCY
+void sound_set_hw_eq_band4_frequency(int value);
+#endif
+#ifdef AUDIOHW_HAVE_EQ_BAND4_WIDTH
+void sound_set_hw_eq_band4_width(int value);
+#endif
+#endif /* AUDIOHW_HAVE_EQ_BAND4 */
+#ifdef AUDIOHW_HAVE_EQ_BAND5
+void sound_set_hw_eq_band5_gain(int value);
+#ifdef AUDIOHW_HAVE_EQ_BAND5_FREQUENCY
+void sound_set_hw_eq_band5_frequency(int value);
+#endif
+#endif /* AUDIOHW_HAVE_EQ_BAND5 */
+#endif /* AUDIOHW_HAVE_EQ */
+
#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
void sound_set_loudness(int value);
void sound_set_avc(int value);
diff --git a/firmware/export/wm8978.h b/firmware/export/wm8978.h
index 270c666a4a..4081d05a89 100644
--- a/firmware/export/wm8978.h
+++ b/firmware/export/wm8978.h
@@ -26,6 +26,19 @@
#define VOLUME_MIN -900
#define VOLUME_MAX 60
+#define AUDIOHW_CAPS (EQ_CAP | PRESCALER_CAP | DEPTH_3D_CAP)
+/* Filter bitmask */
+#define AUDIOHW_EQ_BAND_CAPS ((EQ_CAP << 0) | (EQ_CAP << 1) | \
+ (EQ_CAP << 2) | (EQ_CAP << 3) | \
+ (EQ_CAP << 4))
+/* Filters that can adjust cutoff and center frequency */
+#define AUDIOHW_EQ_FREQUENCY_CAPS ((EQ_CAP << 0) | (EQ_CAP << 1) | \
+ (EQ_CAP << 2) | (EQ_CAP << 3) | \
+ (EQ_CAP << 4))
+/* Filters that can adjust band width */
+#define AUDIOHW_EQ_WIDTH_CAPS ((EQ_CAP << 1) | (EQ_CAP << 2) | \
+ (EQ_CAP << 3))
+
int tenthdb2master(int db);
void audiohw_set_headphone_vol(int vol_l, int vol_r);
void audiohw_set_recsrc(int source, bool recording);
diff --git a/firmware/sound.c b/firmware/sound.c
index b56e610034..fb2f353d71 100644
--- a/firmware/sound.c
+++ b/firmware/sound.c
@@ -48,8 +48,13 @@ extern void audiohw_set_volume(int value);
/* dummy for sim */
const struct sound_settings_info audiohw_settings[] = {
[SOUND_VOLUME] = {"dB", 0, 1, VOLUME_MIN / 10, VOLUME_MAX / 10, -25},
+/* Bass and treble tone controls */
+#ifdef AUDIOHW_HAVE_BASS
[SOUND_BASS] = {"dB", 0, 1, -24, 24, 0},
+#endif
+#ifdef AUDIOHW_HAVE_TREBLE
[SOUND_TREBLE] = {"dB", 0, 1, -24, 24, 0},
+#endif
[SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0},
[SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0},
[SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100},
@@ -64,6 +69,50 @@ const struct sound_settings_info audiohw_settings[] = {
#if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
[SOUND_TREBLE_CUTOFF] = {"", 0, 1, 1, 4, 1},
#endif
+#if defined(AUDIOHW_HAVE_DEPTH_3D)
+ [SOUND_DEPTH_3D] = {"%", 0, 1, 0, 15, 0},
+#endif
+/* Hardware EQ tone controls */
+#if defined(AUDIOHW_HAVE_EQ_BAND1)
+ [SOUND_EQ_BAND1_GAIN] = {"dB", 0, 1, -12, 12, 0},
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND2)
+ [SOUND_EQ_BAND2_GAIN] = {"dB", 0, 1, -12, 12, 0},
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND3)
+ [SOUND_EQ_BAND3_GAIN] = {"dB", 0, 1, -12, 12, 0},
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND4)
+ [SOUND_EQ_BAND4_GAIN] = {"dB", 0, 1, -12, 12, 0},
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND5)
+ [SOUND_EQ_BAND5_GAIN] = {"dB", 0, 1, -12, 12, 0},
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND1_FREQUENCY)
+ [SOUND_EQ_BAND1_FREQUENCY] = {"", 0, 1, 1, 4, 1},
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND2_FREQUENCY)
+ [SOUND_EQ_BAND2_FREQUENCY] = {"", 0, 1, 1, 4, 1},
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND3_FREQUENCY)
+ [SOUND_EQ_BAND3_FREQUENCY] = {"", 0, 1, 1, 4, 1},
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND4_FREQUENCY)
+ [SOUND_EQ_BAND4_FREQUENCY] = {"", 0, 1, 1, 4, 1},
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND5_FREQUENCY)
+ [SOUND_EQ_BAND5_FREQUENCY] = {"", 0, 1, 1, 4, 1},
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND2_WIDTH)
+ [SOUND_EQ_BAND2_WIDTH] = {"", 0, 1, 0, 1, 0},
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND3_WIDTH)
+ [SOUND_EQ_BAND3_WIDTH] = {"", 0, 1, 0, 1, 0},
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND4_WIDTH)
+ [SOUND_EQ_BAND4_WIDTH] = {"", 0, 1, 0, 1, 0},
+#endif
+
#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
[SOUND_LOUDNESS] = {"dB", 0, 1, 0, 17, 0},
[SOUND_AVC] = {"", 0, 1, -1, 4, 0},
@@ -111,8 +160,12 @@ static sound_set_type * const sound_set_fns[] =
{
[0 ... SOUND_LAST_SETTING-1] = NULL,
[SOUND_VOLUME] = sound_set_volume,
+#if defined(AUDIOHW_HAVE_BASS)
[SOUND_BASS] = sound_set_bass,
+#endif
+#if defined(AUDIOHW_HAVE_TREBLE)
[SOUND_TREBLE] = sound_set_treble,
+#endif
[SOUND_BALANCE] = sound_set_balance,
[SOUND_CHANNELS] = sound_set_channels,
[SOUND_STEREO_WIDTH] = sound_set_stereo_width,
@@ -132,6 +185,49 @@ static sound_set_type * const sound_set_fns[] =
#if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
[SOUND_TREBLE_CUTOFF] = sound_set_treble_cutoff,
#endif
+#if defined(AUDIOHW_HAVE_DEPTH_3D)
+ [SOUND_DEPTH_3D] = sound_set_depth_3d,
+#endif
+/* Hardware EQ tone controls */
+#if defined(AUDIOHW_HAVE_EQ)
+ [SOUND_EQ_BAND1_GAIN] = sound_set_hw_eq_band1_gain,
+#if defined(AUDIOHW_HAVE_EQ_BAND1_FREQUENCY)
+ [SOUND_EQ_BAND1_FREQUENCY] = sound_set_hw_eq_band1_frequency,
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND2)
+ [SOUND_EQ_BAND2_GAIN] = sound_set_hw_eq_band2_gain,
+#if defined(AUDIOHW_HAVE_EQ_BAND2_FREQUENCY)
+ [SOUND_EQ_BAND2_FREQUENCY] = sound_set_hw_eq_band2_frequency,
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND2_WIDTH)
+ [SOUND_EQ_BAND2_WIDTH] = sound_set_hw_eq_band2_width,
+#endif
+#endif /* AUDIOHW_HAVE_EQ_BAND2 */
+#if defined(AUDIOHW_HAVE_EQ_BAND3)
+ [SOUND_EQ_BAND3_GAIN] = sound_set_hw_eq_band3_gain,
+#if defined(AUDIOHW_HAVE_EQ_BAND3_FREQUENCY)
+ [SOUND_EQ_BAND3_FREQUENCY] = sound_set_hw_eq_band3_frequency,
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND3_WIDTH)
+ [SOUND_EQ_BAND3_WIDTH] = sound_set_hw_eq_band3_width,
+#endif
+#endif /* AUDIOHW_HAVE_EQ_BAND3 */
+#if defined(AUDIOHW_HAVE_EQ_BAND4)
+ [SOUND_EQ_BAND4_GAIN] = sound_set_hw_eq_band4_gain,
+#if defined(AUDIOHW_HAVE_EQ_BAND4_FREQUENCY)
+ [SOUND_EQ_BAND4_FREQUENCY] = sound_set_hw_eq_band4_frequency,
+#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND4_WIDTH)
+ [SOUND_EQ_BAND4_WIDTH] = sound_set_hw_eq_band4_width,
+#endif
+#endif /* AUDIOHW_HAVE_EQ_BAND4 */
+#if defined(AUDIOHW_HAVE_EQ_BAND5)
+ [SOUND_EQ_BAND5_GAIN] = sound_set_hw_eq_band5_gain,
+#if defined(AUDIOHW_HAVE_EQ_BAND5_FREQUENCY)
+ [SOUND_EQ_BAND5_FREQUENCY] = sound_set_hw_eq_band5_frequency,
+#endif
+#endif /* AUDIOHW_HAVE_EQ_BAND5 */
+#endif /* AUDIOHW_HAVE_EQ */
};
sound_set_type* sound_get_fn(int setting)
@@ -174,8 +270,15 @@ static int tenthdb2reg(int db)
/* all values in tenth of dB MAS3507D UDA1380 */
int current_volume = 0; /* -780..+180 -840.. 0 */
int current_balance = 0; /* -960..+960 -840..+840 */
+#ifdef AUDIOHW_HAVE_TREBLE
int current_treble = 0; /* -150..+150 0.. +60 */
+#endif
+#ifdef AUDIOHW_HAVE_BASS
int current_bass = 0; /* -150..+150 0..+240 */
+#endif
+#ifdef AUDIOHW_HAVE_EQ
+int current_eq_band_gain[AUDIOHW_EQ_BAND_NUM];
+#endif
static void set_prescaled_volume(void)
{
@@ -191,10 +294,18 @@ static void set_prescaled_volume(void)
|| defined(HAVE_WM8711) || defined(HAVE_WM8721) || defined(HAVE_WM8731) \
|| defined(HAVE_WM8758) || defined(HAVE_WM8985) || defined(HAVE_UDA1341))
+#if defined(AUDIOHW_HAVE_BASS) && defined(AUDIOHW_HAVE_TREBLE)
prescale = MAX(current_bass, current_treble);
+#endif
+#if defined(AUDIOHW_HAVE_EQ)
+ int i;
+ for (i = 0; i < AUDIOHW_EQ_BAND_NUM; i++)
+ prescale = MAX(current_eq_band_gain[i], prescale);
+#endif
+
if (prescale < 0)
prescale = 0; /* no need to prescale if we don't boost
- bass or treble */
+ bass, treble or eq band */
/* Gain up the analog volume to compensate the prescale gain reduction,
* but if this would push the volume over the top, reduce prescaling
@@ -289,6 +400,7 @@ void sound_set_balance(int value)
#endif
}
+#ifdef AUDIOHW_HAVE_BASS
void sound_set_bass(int value)
{
if(!audio_is_initialized)
@@ -302,17 +414,19 @@ void sound_set_bass(int value)
#endif
#endif
-#if defined(AUDIOHW_HAVE_BASS)
- audiohw_set_bass(value);
-#else
+#if defined(HAVE_SW_TONE_CONTROLS)
dsp_callback(DSP_CALLBACK_SET_BASS, current_bass);
+#else
+ audiohw_set_bass(value);
#endif
#if !defined(AUDIOHW_HAVE_CLIPPING)
set_prescaled_volume();
#endif
}
+#endif /* AUDIOHW_HAVE_BASS */
+#ifdef AUDIOHW_HAVE_TREBLE
void sound_set_treble(int value)
{
if(!audio_is_initialized)
@@ -326,16 +440,37 @@ void sound_set_treble(int value)
#endif
#endif
-#if defined(AUDIOHW_HAVE_TREBLE)
- audiohw_set_treble(value);
-#else
+#if defined(HAVE_SW_TONE_CONTROLS)
dsp_callback(DSP_CALLBACK_SET_TREBLE, current_treble);
+#else
+ audiohw_set_treble(value);
#endif
#if !defined(AUDIOHW_HAVE_CLIPPING)
set_prescaled_volume();
#endif
}
+#endif /* AUDIOHW_HAVE_TREBLE */
+
+#if defined(AUDIOHW_HAVE_BASS_CUTOFF)
+void sound_set_bass_cutoff(int value)
+{
+ if(!audio_is_initialized)
+ return;
+
+ audiohw_set_bass_cutoff(value);
+}
+#endif
+
+#if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
+void sound_set_treble_cutoff(int value)
+{
+ if(!audio_is_initialized)
+ return;
+
+ audiohw_set_treble_cutoff(value);
+}
+#endif
void sound_set_channels(int value)
{
@@ -361,26 +496,208 @@ void sound_set_stereo_width(int value)
#endif
}
-#if defined(AUDIOHW_HAVE_BASS_CUTOFF)
-void sound_set_bass_cutoff(int value)
+#if defined(AUDIOHW_HAVE_DEPTH_3D)
+void sound_set_depth_3d(int value)
{
if(!audio_is_initialized)
return;
- audiohw_set_bass_cutoff(value);
+ audiohw_set_depth_3d(value);
}
#endif
-#if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
-void sound_set_treble_cutoff(int value)
+#if defined(AUDIOHW_HAVE_EQ)
+int sound_enum_hw_eq_band_setting(unsigned int band,
+ unsigned int band_setting)
+{
+ static const int8_t
+ sound_hw_eq_band_setting[AUDIOHW_EQ_SETTING_NUM][AUDIOHW_EQ_BAND_NUM] =
+ {
+ [AUDIOHW_EQ_GAIN] =
+ {
+ [0 ... AUDIOHW_EQ_BAND_NUM-1] = -1,
+ [AUDIOHW_EQ_BAND1] = SOUND_EQ_BAND1_GAIN,
+ #ifdef AUDIOHW_HAVE_EQ_BAND2
+ [AUDIOHW_EQ_BAND2] = SOUND_EQ_BAND2_GAIN,
+ #endif
+ #ifdef AUDIOHW_HAVE_EQ_BAND3
+ [AUDIOHW_EQ_BAND3] = SOUND_EQ_BAND3_GAIN,
+ #endif
+ #ifdef AUDIOHW_HAVE_EQ_BAND4
+ [AUDIOHW_EQ_BAND4] = SOUND_EQ_BAND4_GAIN,
+ #endif
+ #ifdef AUDIOHW_HAVE_EQ_BAND5
+ [AUDIOHW_EQ_BAND5] = SOUND_EQ_BAND5_GAIN,
+ #endif
+ },
+#ifdef AUDIOHW_HAVE_EQ_FREQUENCY
+ [AUDIOHW_EQ_FREQUENCY] =
+ {
+ [0 ... AUDIOHW_EQ_BAND_NUM-1] = -1,
+ #ifdef AUDIOHW_HAVE_EQ_BAND1_FREQUENCY
+ [AUDIOHW_EQ_BAND1] = SOUND_EQ_BAND1_FREQUENCY,
+ #endif
+ #ifdef AUDIOHW_HAVE_EQ_BAND2_FREQUENCY
+ [AUDIOHW_EQ_BAND2] = SOUND_EQ_BAND2_FREQUENCY,
+ #endif
+ #ifdef AUDIOHW_HAVE_EQ_BAND3_FREQUENCY
+ [AUDIOHW_EQ_BAND3] = SOUND_EQ_BAND3_FREQUENCY,
+ #endif
+ #ifdef AUDIOHW_HAVE_EQ_BAND4_FREQUENCY
+ [AUDIOHW_EQ_BAND4] = SOUND_EQ_BAND4_FREQUENCY,
+ #endif
+ #ifdef AUDIOHW_HAVE_EQ_BAND5_FREQUENCY
+ [AUDIOHW_EQ_BAND5] = SOUND_EQ_BAND5_FREQUENCY,
+ #endif
+ },
+#endif /* AUDIOHW_HAVE_EQ_FREQUENCY */
+#ifdef AUDIOHW_HAVE_EQ_WIDTH
+ [AUDIOHW_EQ_WIDTH] =
+ {
+ [0 ... AUDIOHW_EQ_BAND_NUM-1] = -1,
+ #ifdef AUDIOHW_HAVE_EQ_BAND2_WIDTH
+ [AUDIOHW_EQ_BAND2] = SOUND_EQ_BAND2_WIDTH,
+ #endif
+ #ifdef AUDIOHW_HAVE_EQ_BAND3_WIDTH
+ [AUDIOHW_EQ_BAND3] = SOUND_EQ_BAND3_WIDTH,
+ #endif
+ #ifdef AUDIOHW_HAVE_EQ_BAND4_WIDTH
+ [AUDIOHW_EQ_BAND4] = SOUND_EQ_BAND4_WIDTH,
+ #endif
+ },
+#endif /* AUDIOHW_HAVE_EQ_WIDTH */
+ };
+
+ if (band < AUDIOHW_EQ_BAND_NUM && band_setting < AUDIOHW_EQ_SETTING_NUM)
+ return sound_hw_eq_band_setting[band_setting][band];
+
+ return -1;
+}
+
+static void sound_set_hw_eq_band_gain(unsigned int band, int value)
{
if(!audio_is_initialized)
return;
- audiohw_set_treble_cutoff(value);
+ current_eq_band_gain[band] = value;
+ audiohw_set_eq_band_gain(band, value);
+ set_prescaled_volume();
+}
+
+void sound_set_hw_eq_band1_gain(int value)
+{
+ sound_set_hw_eq_band_gain(AUDIOHW_EQ_BAND1, value);
+}
+
+#if defined(AUDIOHW_HAVE_EQ_BAND2)
+void sound_set_hw_eq_band2_gain(int value)
+{
+ sound_set_hw_eq_band_gain(AUDIOHW_EQ_BAND2, value);
+}
+#endif
+
+#if defined(AUDIOHW_HAVE_EQ_BAND3)
+void sound_set_hw_eq_band3_gain(int value)
+{
+ sound_set_hw_eq_band_gain(AUDIOHW_EQ_BAND3, value);
}
#endif
+#if defined(AUDIOHW_HAVE_EQ_BAND4)
+void sound_set_hw_eq_band4_gain(int value)
+{
+ sound_set_hw_eq_band_gain(AUDIOHW_EQ_BAND4, value);
+}
+#endif
+
+#if defined(AUDIOHW_HAVE_EQ_BAND5)
+void sound_set_hw_eq_band5_gain(int value)
+{
+ sound_set_hw_eq_band_gain(AUDIOHW_EQ_BAND5, value);
+}
+#endif
+
+#if defined(AUDIOHW_HAVE_EQ_BAND1_FREQUENCY)
+void sound_set_hw_eq_band1_frequency(int value)
+{
+ if(!audio_is_initialized)
+ return;
+
+ audiohw_set_eq_band_frequency(AUDIOHW_EQ_BAND1, value);
+}
+#endif
+
+#if defined(AUDIOHW_HAVE_EQ_BAND2_FREQUENCY)
+void sound_set_hw_eq_band2_frequency(int value)
+{
+ if(!audio_is_initialized)
+ return;
+
+ audiohw_set_eq_band_frequency(AUDIOHW_EQ_BAND2, value);
+}
+#endif
+
+#if defined(AUDIOHW_HAVE_EQ_BAND3_FREQUENCY)
+void sound_set_hw_eq_band3_frequency(int value)
+{
+ if(!audio_is_initialized)
+ return;
+
+ audiohw_set_eq_band_frequency(AUDIOHW_EQ_BAND3, value);
+}
+#endif
+
+#if defined(AUDIOHW_HAVE_EQ_BAND4_FREQUENCY)
+void sound_set_hw_eq_band4_frequency(int value)
+{
+ if(!audio_is_initialized)
+ return;
+
+ audiohw_set_eq_band_frequency(AUDIOHW_EQ_BAND4, value);
+}
+#endif
+
+#if defined(AUDIOHW_HAVE_EQ_BAND5_FREQUENCY)
+void sound_set_hw_eq_band5_frequency(int value)
+{
+ if(!audio_is_initialized)
+ return;
+
+ audiohw_set_eq_band_frequency(AUDIOHW_EQ_BAND5, value);
+}
+#endif
+
+#if defined(AUDIOHW_HAVE_EQ_BAND2_WIDTH)
+void sound_set_hw_eq_band2_width(int value)
+{
+ if(!audio_is_initialized)
+ return;
+
+ audiohw_set_eq_band_width(AUDIOHW_EQ_BAND2, value);
+}
+#endif
+
+#if defined(AUDIOHW_HAVE_EQ_BAND3_WIDTH)
+void sound_set_hw_eq_band3_width(int value)
+{
+ if(!audio_is_initialized)
+ return;
+
+ audiohw_set_eq_band_width(AUDIOHW_EQ_BAND3, value);
+}
+#endif
+
+#if defined(AUDIOHW_HAVE_EQ_BAND4_WIDTH)
+void sound_set_hw_eq_band4_width(int value)
+{
+ if(!audio_is_initialized)
+ return;
+
+ audiohw_set_eq_band_width(AUDIOHW_EQ_BAND4, value);
+}
+#endif
+#endif /* AUDIOHW_HAVE_EQ */
+
#if ((CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F))
void sound_set_loudness(int value)
{
@@ -572,6 +889,10 @@ int sound_val2phys(int setting, int value)
break;
#endif
+ case SOUND_DEPTH_3D:
+ result = (100 * value + 8) / 15;
+ break;
+
default:
result = value;
}
diff --git a/uisimulator/sdl/sound.c b/uisimulator/sdl/sound.c
index dd5e4345aa..0f8d5d4934 100644
--- a/uisimulator/sdl/sound.c
+++ b/uisimulator/sdl/sound.c
@@ -385,6 +385,23 @@ void audiohw_set_bass_cutoff(int value) { (void)value; }
#if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
void audiohw_set_treble_cutoff(int value){ (void)value; }
#endif
+/* EQ-based tone controls */
+#if defined(AUDIOHW_HAVE_EQ)
+void audiohw_set_eq_band_gain(unsigned int band, int value)
+ { (void)band; (void)value; }
+#endif
+#if defined(AUDIOHW_HAVE_EQ_FREQUENCY)
+void audiohw_set_eq_band_frequency(unsigned int band, int value)
+ { (void)band; (void)value; }
+#endif
+#if defined(AUDIOHW_HAVE_EQ_WIDTH)
+void audiohw_set_eq_band_width(unsigned int band, int value)
+ { (void)band; (void)value; }
+#endif
+#if defined(AUDIOHW_HAVE_DEPTH_3D)
+void audiohw_set_depth_3d(int value)
+ { (void)value; }
+#endif
#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
int mas_codec_readreg(int reg)
{