summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2010-05-15 13:09:45 +0000
committerMichael Sevakis <jethead71@rockbox.org>2010-05-15 13:09:45 +0000
commit80d0d15ca9b253f8a446f50cf25d3d4b850bcfd1 (patch)
tree2598d3a019c33d6f9ea76010fd6d3a8301ef87a0
parent0f77db73469920f0b0006f696ddb36029338c378 (diff)
downloadrockbox-80d0d15ca9b253f8a446f50cf25d3d4b850bcfd1.tar.gz
rockbox-80d0d15ca9b253f8a446f50cf25d3d4b850bcfd1.zip
Gigabeat S: Fully enable access to hardware tone controls and 3-D effect feature. Under the hood, it's designated a hardware equalizer since it is one. Implement code framework for hardware EQ in general. Menu aspect is well abstracted and so the UI and strings can be changed around if taste doesn't quite suit. So far the emphasis is distinction of the UI labelling from the software EQ so that it's clear the settings are for a different thing.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26051 a1c6a512-1295-4272-9138-f99709370657
-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)
{