From 0c7b7873984e04941c9f21fa272638018fdb9a16 Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Fri, 12 Apr 2013 23:35:47 -0400 Subject: [PATCH] Straighten out the mad twisted state of sound.c and related areas. This is going right in since it's long overdue. If anything is goofed, drop me a line or just tweak it yourself if you know what's wrong. :-) Make HW/SW codec interface more uniform when emulating HW functionality on SWCODEC for functions such as "audiohw_set_pitch". The firmware-to- DSP plumbing is in firmware/drivers/audiohw-swcodec.c. "sound_XXX" APIs are all in sound.c with none in DSP code any longer. Reduce number of settings definitions needed by each codec by providing defaults for common ones like balance, channels and SW tone controls. Remove need for separate SIM code and tables and add virtual codec header for hosted targets. Change-Id: I3f23702bca054fc9bda40f49824ce681bb7f777b --- apps/fixedpoint.c | 2 +- apps/settings.c | 2 +- firmware/SOURCES | 2 + firmware/drivers/audio/aic3x.c | 7 +- firmware/drivers/audio/ak4537.c | 27 +- firmware/drivers/audio/as3514.c | 42 +- firmware/drivers/audio/audiohw-swcodec.c | 76 +++ firmware/drivers/audio/cs42l55.c | 30 +- firmware/drivers/audio/dac3550a.c | 9 - firmware/drivers/audio/dummy_codec.c | 12 +- firmware/drivers/audio/imx233-codec.c | 26 +- firmware/drivers/audio/mas35xx.c | 71 +-- firmware/drivers/audio/rk27xx_codec.c | 19 +- firmware/drivers/audio/sdl.c | 105 +--- firmware/drivers/audio/tlv320.c | 9 +- firmware/drivers/audio/tsc2100.c | 41 +- firmware/drivers/audio/uda1341.c | 26 +- firmware/drivers/audio/uda1380.c | 37 +- firmware/drivers/audio/wm8731.c | 55 +- firmware/drivers/audio/wm8751.c | 75 +-- firmware/drivers/audio/wm8758.c | 37 -- firmware/drivers/audio/wm8975.c | 51 +- firmware/drivers/audio/wm8978.c | 77 +-- firmware/drivers/audio/wm8985.c | 46 +- firmware/export/aic3x.h | 6 +- firmware/export/ak4537.h | 4 +- firmware/export/as3514.h | 39 +- firmware/export/audiohw.h | 149 ++++-- firmware/export/audiohw_settings.h | 143 +++++ firmware/export/cs42l55.h | 15 +- firmware/export/dac3550a.h | 1 - firmware/export/dummy_codec.h | 2 +- firmware/export/hosted_codec.h | 30 ++ firmware/export/imx233-codec.h | 15 +- firmware/export/jz4740-codec.h | 13 +- firmware/export/mas35xx.h | 59 ++- firmware/export/rk27xx_codec.h | 10 +- firmware/export/sound.h | 14 - firmware/export/tlv320.h | 28 +- firmware/export/tsc2100.h | 9 +- firmware/export/uda1341.h | 15 +- firmware/export/uda1380.h | 17 +- firmware/export/wm8731.h | 11 +- firmware/export/wm8751.h | 38 +- firmware/export/wm8758.h | 21 +- firmware/export/wm8975.h | 16 +- firmware/export/wm8978.h | 40 +- firmware/export/wm8985.h | 22 +- firmware/include/fixedpoint.h | 5 + firmware/sound.c | 493 +++++------------- firmware/target/arm/pnx0101/pcm-pnx0101.c | 6 + .../target/mips/ingenic_jz47xx/codec-jz4740.c | 24 - lib/rbcodec/dsp/dsp_misc.c | 83 +-- lib/rbcodec/dsp/dsp_misc.h | 16 +- lib/rbcodec/test/warble.c | 2 +- 55 files changed, 1003 insertions(+), 1227 deletions(-) create mode 100644 firmware/drivers/audio/audiohw-swcodec.c create mode 100644 firmware/export/audiohw_settings.h create mode 100644 firmware/export/hosted_codec.h diff --git a/apps/fixedpoint.c b/apps/fixedpoint.c index 5051cc78e7..b212929245 100644 --- a/apps/fixedpoint.c +++ b/apps/fixedpoint.c @@ -353,7 +353,7 @@ long fp16_exp(int x) /** FIXED POINT EXP10 * Return 10^x as FP integer. Argument is FP integer. */ -static long fp_exp10(long x, unsigned int fracbits) +long fp_exp10(long x, unsigned int fracbits) { long k; long z; diff --git a/apps/settings.c b/apps/settings.c index 1bb6c74b43..0984143dbb 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -723,7 +723,7 @@ void settings_apply_pm_range(void) void sound_settings_apply(void) { #if CONFIG_CODEC == SWCODEC - sound_set_dsp_callback(dsp_callback); + audiohw_swcodec_set_callback(dsp_callback); #endif #ifdef AUDIOHW_HAVE_BASS sound_set(SOUND_BASS, global_settings.bass); diff --git a/firmware/SOURCES b/firmware/SOURCES index 964d57ff5d..e6c0b967d4 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -361,6 +361,8 @@ pcm_sw_volume.c #ifdef HAVE_RECORDING enc_base.c #endif /* HAVE_RECORDING */ + +drivers/audio/audiohw-swcodec.c #endif /* BOOTLOADER */ #endif /* SWCODEC */ diff --git a/firmware/drivers/audio/aic3x.c b/firmware/drivers/audio/aic3x.c index 97eb17ebef..08c4db3f53 100644 --- a/firmware/drivers/audio/aic3x.c +++ b/firmware/drivers/audio/aic3x.c @@ -44,7 +44,7 @@ const struct sound_settings_info audiohw_settings[] = { }; /* convert tenth of dB volume to master volume register value */ -int tenthdb2master(int db) +static int vol_tenthdb2hw(int db) { /* 0 to -63.0dB in 1dB steps, aic3x can goto -63.5 in 0.5dB steps */ if (db < VOLUME_MIN) @@ -270,8 +270,11 @@ void audiohw_set_frequency(int fsel) /* TODO */ } -void audiohw_set_headphone_vol(int vol_l, int vol_r) +void audiohw_set_volume(int vol_l, int vol_r) { + vol_l = vol_tenthdb2hw(vol_l); + vol_r = vol_tenthdb2hw(vol_r); + if ((volume_left & 0x7F) == (vol_l & 0x7F) && (volume_right & 0x7F) == (vol_r & 0x7F)) { diff --git a/firmware/drivers/audio/ak4537.c b/firmware/drivers/audio/ak4537.c index c3ce02a3af..4a9010d4e7 100644 --- a/firmware/drivers/audio/ak4537.c +++ b/firmware/drivers/audio/ak4537.c @@ -80,7 +80,7 @@ static void codec_set_active(int active) #endif /* convert tenth of dB volume (-1270..0) to master volume register value */ -int tenthdb2master(int db) +static int vol_tenthdb2hw(int db) { if (db < VOLUME_MIN) return 0xff; /* mute */ @@ -90,29 +90,6 @@ int tenthdb2master(int db) return ((-db)/5); } -int sound_val2phys(int setting, int value) -{ - int result; - - switch(setting) - { -#ifdef HAVE_RECORDING - case SOUND_LEFT_GAIN: - case SOUND_RIGHT_GAIN: - result = (value - 23) * 15; /* fix */ - break; - case SOUND_MIC_GAIN: - result = value * 200; /* fix */ - break; -#endif - default: - result = value; - break; - } - - return result; -} - /*static void audiohw_mute(bool mute) { if (mute) @@ -232,6 +209,8 @@ void audiohw_close(void) void audiohw_set_master_vol(int vol_l, int vol_r) { + vol_l = vol_tenthdb2hw(vol_l); + vol_r = vol_tenthdb2hw(vol_r); akc_write(AK4537_ATTL, vol_l & 0xff); akc_write(AK4537_ATTR, vol_r & 0xff); } diff --git a/firmware/drivers/audio/as3514.c b/firmware/drivers/audio/as3514.c index 5f18bc6ec1..b9118f9fcf 100644 --- a/firmware/drivers/audio/as3514.c +++ b/firmware/drivers/audio/as3514.c @@ -63,21 +63,6 @@ #endif -const struct sound_settings_info audiohw_settings[] = { - [SOUND_VOLUME] = {"dB", 0, 1, VOLUME_MIN/10, 6, -25}, - /* HAVE_SW_TONE_CONTROLS */ - [SOUND_BASS] = {"dB", 0, 1, -24, 24, 0}, - [SOUND_TREBLE] = {"dB", 0, 1, -24, 24, 0}, - [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, - [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, - [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, -#ifdef HAVE_RECORDING - [SOUND_MIC_GAIN] = {"dB", 1, 1, 0, 39, 23}, - [SOUND_LEFT_GAIN] = {"dB", 1, 1, 0, 31, 23}, - [SOUND_RIGHT_GAIN] = {"dB", 1, 1, 0, 31, 23}, -#endif -}; - /* Shadow registers */ static uint8_t as3514_regs[AS3514_NUM_AUDIO_REGS]; /* 8-bit registers */ @@ -112,7 +97,7 @@ static void as3514_write_masked(unsigned int reg, unsigned int bits, } /* convert tenth of dB volume to master volume register value */ -int tenthdb2master(int db) +static int vol_tenthdb2hw(int db) { /* +6 to -73.5dB (or -81.0 dB) in 1.5dB steps == 53 (or 58) levels */ if (db < VOLUME_MIN) { @@ -124,22 +109,6 @@ int tenthdb2master(int db) } } -int sound_val2phys(int setting, int value) -{ - switch(setting) - { -#if defined(HAVE_RECORDING) - case SOUND_LEFT_GAIN: - case SOUND_RIGHT_GAIN: - case SOUND_MIC_GAIN: - return (value - 23) * 15; -#endif - - default: - return value; - } -} - /* * Initialise the PP I2C and I2S. */ @@ -276,6 +245,9 @@ void audiohw_set_master_vol(int vol_l, int vol_r) unsigned int hph_r, hph_l; unsigned int mix_l, mix_r; + vol_l = vol_tenthdb2hw(vol_l); + vol_r = vol_tenthdb2hw(vol_r); + if (vol_l == 0 && vol_r == 0) { audiohw_mute(true); return; @@ -322,12 +294,14 @@ void audiohw_set_master_vol(int vol_l, int vol_r) } #if 0 /* unused */ -void audiohw_set_lineout_vol(int vol_l, int vol_r) +void audiohw_set_lineout_volume(int vol_l, int vol_r) { #ifdef HAVE_AS3543 /* line out volume is set in the same registers */ - audiohw_set_master_vol(vol_l, vol_r); + audiohw_set_master_volume(vol_l, vol_r); #else + vol_l = vol_tenthdb2hw(vol_l); + vol_r = vol_tenthdb2hw(vol_r); as3514_write_masked(AS3514_LINE_OUT_R, vol_r, AS3514_VOL_MASK); as3514_write_masked(AS3514_LINE_OUT_L, vol_l, AS3514_VOL_MASK); #endif diff --git a/firmware/drivers/audio/audiohw-swcodec.c b/firmware/drivers/audio/audiohw-swcodec.c new file mode 100644 index 0000000000..45b21183ad --- /dev/null +++ b/firmware/drivers/audio/audiohw-swcodec.c @@ -0,0 +1,76 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2007 by Thom Johansen + * + * 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 "config.h" +#include "system.h" +#include "sound.h" +#include "dsp_misc.h" + +/* Linking audio hardware calls to SWCODEC DSP emulation */ + +static audiohw_swcodec_cb_type callback = NULL; + +void audiohw_swcodec_set_callback(audiohw_swcodec_cb_type func) +{ + callback = func; +} + +/** Functions exported by audiohw.h **/ + +void audiohw_set_channel(int value) +{ + callback(DSP_CALLBACK_SET_CHANNEL_CONFIG, value); +} + +void audiohw_set_stereo_width(int value) +{ + callback(DSP_CALLBACK_SET_STEREO_WIDTH, value); +} + +#ifdef HAVE_SW_TONE_CONTROLS +void audiohw_set_bass(int value) +{ + callback(DSP_CALLBACK_SET_BASS, value); +} + +void audiohw_set_treble(int value) +{ + callback(DSP_CALLBACK_SET_TREBLE, value); +} +#endif /* HAVE_SW_TONE_CONTROLS */ + +#ifndef AUDIOHW_HAVE_PRESCALER +void audiohw_set_prescaler(int value) +{ + callback(DSP_CALLBACK_SET_PRESCALE, value); +} +#endif /* AUDIOHW_HAVE_PRESCALER */ + +#ifdef HAVE_PITCHCONTROL +void audiohw_set_pitch(int32_t value) +{ + callback(DSP_CALLBACK_SET_PITCH, value); +} + +int32_t audiohw_get_pitch(void) +{ + return callback(DSP_CALLBACK_GET_PITCH, 0); +} +#endif /* HAVE_PITCHCONTROL */ diff --git a/firmware/drivers/audio/cs42l55.c b/firmware/drivers/audio/cs42l55.c index 38380d5a54..75fcd80b77 100644 --- a/firmware/drivers/audio/cs42l55.c +++ b/firmware/drivers/audio/cs42l55.c @@ -29,27 +29,15 @@ #include "cscodec.h" #include "cs42l55.h" -const struct sound_settings_info audiohw_settings[] = { - [SOUND_VOLUME] = {"dB", 0, 1, -60, 12, -25}, - [SOUND_BASS] = {"dB", 1, 15,-105, 120, 0}, - [SOUND_TREBLE] = {"dB", 1, 15,-105, 120, 0}, - [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, - [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, - [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, - [SOUND_BASS_CUTOFF] = {"", 0, 1, 1, 4, 2}, - [SOUND_TREBLE_CUTOFF] = {"", 0, 1, 1, 4, 1}, -}; - static int bass, treble; -/* convert tenth of dB volume (-600..120) to master volume register value */ -int tenthdb2master(int db) +/* convert tenth of dB volume (-600..120) to volume register value */ +static int vol_tenthdb2hw(int db) { /* -60dB to +12dB in 1dB steps */ /* 0001100 == +12dB (0xc) */ /* 0000000 == 0dB (0x0) */ /* 1000100 == -60dB (0x44, this is actually -58dB) */ - if (db < VOLUME_MIN) return HPACTL_HPAMUTE; return (db / 10) & HPACTL_HPAVOL_MASK; } @@ -125,11 +113,8 @@ void audiohw_postinit(void) void audiohw_set_master_vol(int vol_l, int vol_r) { - /* -60dB to +12dB in 1dB steps */ - /* 0001100 == +12dB (0xc) */ - /* 0000000 == 0dB (0x0) */ - /* 1000100 == -60dB (0x44, this is actually -58dB) */ - + vol_l = vol_tenthdb2hw(vol_l); + vol_r = vol_tenthdb2hw(vol_r); cscodec_setbits(HPACTL, HPACTL_HPAVOL_MASK | HPACTL_HPAMUTE, vol_l << HPACTL_HPAVOL_SHIFT); cscodec_setbits(HPBCTL, HPBCTL_HPBVOL_MASK | HPBCTL_HPBMUTE, @@ -138,11 +123,8 @@ void audiohw_set_master_vol(int vol_l, int vol_r) void audiohw_set_lineout_vol(int vol_l, int vol_r) { - /* -60dB to +12dB in 1dB steps */ - /* 0001100 == +12dB (0xc) */ - /* 0000000 == 0dB (0x0) */ - /* 1000100 == -60dB (0x44, this is actually -58dB) */ - + vol_l = vol_tenthdb2hw(vol_l); + vol_r = vol_tenthdb2hw(vol_r); cscodec_setbits(LINEACTL, LINEACTL_LINEAVOL_MASK | LINEACTL_LINEAMUTE, vol_l << LINEACTL_LINEAVOL_SHIFT); cscodec_setbits(LINEBCTL, LINEBCTL_LINEBVOL_MASK | LINEBCTL_LINEBMUTE, diff --git a/firmware/drivers/audio/dac3550a.c b/firmware/drivers/audio/dac3550a.c index 9c6dfbb292..0ff5d8ad21 100644 --- a/firmware/drivers/audio/dac3550a.c +++ b/firmware/drivers/audio/dac3550a.c @@ -27,15 +27,6 @@ static bool line_in_enabled = false; static bool dac_enabled = false; -/* convert tenth of dB volume (-780..+180) to dac3550 register value */ -int tenthdb2reg(int db) -{ - if (db < -540) /* 3 dB steps */ - return (db + 780) / 30; - else /* 1.5 dB steps */ - return (db + 660) / 15; -} - int dac_volume(unsigned int left, unsigned int right, bool deemph) { int ret = 0; diff --git a/firmware/drivers/audio/dummy_codec.c b/firmware/drivers/audio/dummy_codec.c index 94ba04b56a..3e73137eb9 100644 --- a/firmware/drivers/audio/dummy_codec.c +++ b/firmware/drivers/audio/dummy_codec.c @@ -26,16 +26,6 @@ #include "system.h" #include "pcm_sw_volume.h" -const struct sound_settings_info audiohw_settings[] = { - [SOUND_VOLUME] = {"dB", 0, 1, VOLUME_MIN/10, VOLUME_MAX/10, 0}, - /* HAVE_SW_TONE_CONTROLS */ - [SOUND_BASS] = {"dB", 0, 1, -24, 24, 0}, - [SOUND_TREBLE] = {"dB", 0, 1, -24, 24, 0}, - [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, - [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, - [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, -}; - void audiohw_preinit(void) { } void audiohw_postinit(void) { } @@ -48,7 +38,7 @@ void audiohw_set_frequency(int fsel) } #ifdef HAVE_SW_VOLUME_CONTROL -void audiohw_set_master_vol(int vol_l, int vol_r) +void audiohw_set_volume(int vol_l, int vol_r) { /* SW volume for <= 1.0 gain, HW at unity, < VOLUME_MIN == MUTE */ int sw_volume_l = vol_l < VOLUME_MIN ? PCM_MUTE_LEVEL : MIN(vol_l, 0); diff --git a/firmware/drivers/audio/imx233-codec.c b/firmware/drivers/audio/imx233-codec.c index 20edf005e8..ef4e3ca1d5 100644 --- a/firmware/drivers/audio/imx233-codec.c +++ b/firmware/drivers/audio/imx233-codec.c @@ -25,30 +25,6 @@ #include "audioout-imx233.h" #include "audioin-imx233.h" -const struct sound_settings_info audiohw_settings[] = -{ - /* i.MX233 has half dB steps */ - [SOUND_VOLUME] = {"dB", 0, 5, VOLUME_MIN / 10, VOLUME_MAX / 10, -25}, - /* HAVE_SW_TONE_CONTROLS */ - [SOUND_BASS] = {"dB", 0, 1, -24, 24, 0}, - [SOUND_TREBLE] = {"dB", 0, 1, -24, 24, 0}, - [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, - [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, - [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, -#ifdef HAVE_RECORDING - [SOUND_LEFT_GAIN] = {"dB", 1, 1, 0, 31, 23}, - [SOUND_RIGHT_GAIN] = {"dB", 1, 1, 0, 31, 23}, - [SOUND_MIC_GAIN] = {"dB", 1, 1, 0, 1, 0}, -#endif - [SOUND_DEPTH_3D] = {"%", 0, 1, 0, 15, 0}, -}; - -int tenthdb2master(int tdb) -{ - /* Just go from tenth of dB to half to dB */ - return tdb / 5; -} - void audiohw_preinit(void) { imx233_audioout_preinit(); @@ -69,7 +45,7 @@ void audiohw_close(void) void audiohw_set_headphone_vol(int vol_l, int vol_r) { - imx233_audioout_set_hp_vol(vol_l, vol_r); + imx233_audioout_set_hp_vol(vol_l / 5, vol_r / 5); } void audiohw_set_frequency(int fsel) diff --git a/firmware/drivers/audio/mas35xx.c b/firmware/drivers/audio/mas35xx.c index e6cc665109..deb9223187 100644 --- a/firmware/drivers/audio/mas35xx.c +++ b/firmware/drivers/audio/mas35xx.c @@ -26,36 +26,6 @@ #include "system.h" /* MAX MIN macros */ #include "audiohw.h" -const struct sound_settings_info audiohw_settings[] = { -#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) - [SOUND_VOLUME] = {"dB", 0, 1,-100, 12, -25}, - [SOUND_BASS] = {"dB", 0, 1, -12, 12, 6}, - [SOUND_TREBLE] = {"dB", 0, 1, -12, 12, 6}, -#elif CONFIG_CODEC == MAS3507D - [SOUND_VOLUME] = {"dB", 0, 1, -78, 18, -18}, - [SOUND_BASS] = {"dB", 0, 1, -15, 15, 7}, - [SOUND_TREBLE] = {"dB", 0, 1, -15, 15, 7}, -#endif - [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, - [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, - [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, -#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) - [SOUND_LOUDNESS] = {"dB", 0, 1, 0, 17, 0}, - [SOUND_AVC] = {"", 0, 1, -1, 4, 0}, - [SOUND_MDB_STRENGTH] = {"dB", 0, 1, 0, 127, 48}, - [SOUND_MDB_HARMONICS] = {"%", 0, 1, 0, 100, 50}, - [SOUND_MDB_CENTER] = {"Hz", 0, 10, 20, 300, 60}, - [SOUND_MDB_SHAPE] = {"Hz", 0, 10, 50, 300, 90}, - [SOUND_MDB_ENABLE] = {"", 0, 1, 0, 1, 0}, - [SOUND_SUPERBASS] = {"", 0, 1, 0, 1, 0}, -#endif -#if CONFIG_CODEC == MAS3587F && defined(HAVE_RECORDING) - [SOUND_LEFT_GAIN] = {"dB", 1, 1, 0, 15, 8}, - [SOUND_RIGHT_GAIN] = {"dB", 1, 1, 0, 15, 8}, - [SOUND_MIC_GAIN] = {"dB", 1, 1, 0, 15, 2}, -#endif -}; - int channel_configuration = SOUND_CHAN_STEREO; int stereo_width = 100; @@ -65,7 +35,6 @@ unsigned long loudness_shadow = 0; unsigned long shadow_io_control_main; #endif - static void set_channel_config(void) { /* default values: stereo */ @@ -185,6 +154,22 @@ void audiohw_set_treble(int val) #endif } +#if (CONFIG_CODEC == MAS3507D) +/* convert tenth of dB volume (-780..+180) to dac3550 register value */ +static unsigned int tenthdb2reg(int db) +{ + if (db < -540) /* 3 dB steps */ + return (db + 780) / 30; + else /* 1.5 dB steps */ + return (db + 660) / 15; +} + +void audiohw_set_volume(int vol_l, int vol_r) +{ + dac_volume(tenthdb2reg(vol_l), tenthdb2reg(vol_r), false); +} +#endif /* CONFIG_CODEC == MAS3507D */ + #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) void audiohw_set_volume(int val) { @@ -268,14 +253,32 @@ void audiohw_set_balance(int val) mas_codec_writereg(MAS_REG_BALANCE, tmp); } -void audiohw_set_pitch(unsigned long val) +/* This functionality works by telling the decoder that we have another + crystal frequency than we actually have. It will adjust its internal + parameters and the result is that the audio is played at another pitch. +*/ +static int32_t last_pitch = PITCH_SPEED_100; + +void audiohw_set_pitch(int32_t val) { - mas_writemem(MAS_BANK_D0, MAS_D0_OFREQ_CONTROL, &val, 1); + if (val == last_pitch) + return; + + /* Calculate the new (bogus) frequency */ + unsigned long reg = 18432 * PITCH_SPEED_100 / val; + mas_writemem(MAS_BANK_D0, MAS_D0_OFREQ_CONTROL, ®, 1); /* We must tell the MAS that the frequency has changed. * This will unfortunately cause a short silence. */ + mas_writemem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, + &shadow_io_control_main, 1); - mas_writemem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, &shadow_io_control_main, 1); + last_pitch = val; +} + +int32_t audiohw_get_pitch(void) +{ + return last_pitch; } #endif /* CONFIG_CODEC == MAS3587F || CONFIG_CODEC == MAS3539F */ diff --git a/firmware/drivers/audio/rk27xx_codec.c b/firmware/drivers/audio/rk27xx_codec.c index 6f71214df4..aada17cc0a 100644 --- a/firmware/drivers/audio/rk27xx_codec.c +++ b/firmware/drivers/audio/rk27xx_codec.c @@ -27,21 +27,6 @@ #include "system.h" #include "i2c-rk27xx.h" -const struct sound_settings_info audiohw_settings[] = { - [SOUND_VOLUME] = {"dB", 0, 1, -34, 4, -25}, - /* HAVE_SW_TONE_CONTROLS */ - [SOUND_BASS] = {"dB", 0, 1, -24, 24, 0}, - [SOUND_TREBLE] = {"dB", 0, 1, -24, 24, 0}, - [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, - [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, - [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, -#ifdef HAVE_RECORDING /* disabled for now */ - [SOUND_LEFT_GAIN] = {"dB", 2, 75, -1725, 3000, 0}, - [SOUND_RIGHT_GAIN] = {"dB", 2, 75, -1725, 3000, 0}, - [SOUND_MIC_GAIN] = {"dB", 0, 1, 0, 20, 20}, -#endif -}; - /* private functions to read/write codec registers */ static int codec_write(uint8_t reg, uint8_t val) { @@ -66,7 +51,7 @@ static void audiohw_mute(bool mute) } /* public functions */ -int tenthdb2master(int tdb) +static int vol_tenthdb2hw(int tdb) { /* we lie here a bit and present 0.5dB gain steps * but codec has 'variable' gain steps (0.5, 1.0, 2.0) @@ -150,6 +135,8 @@ void audiohw_set_frequency(int fsel) void audiohw_set_master_vol(int vol_l, int vol_r) { + vol_l = vol_tenthdb2hw(vol_l); + vol_r = vol_tenthdb2hw(vol_r); if (vol_l > 31 || vol_r > 31) { diff --git a/firmware/drivers/audio/sdl.c b/firmware/drivers/audio/sdl.c index 3c7cc55ce9..eea10ad12c 100644 --- a/firmware/drivers/audio/sdl.c +++ b/firmware/drivers/audio/sdl.c @@ -32,107 +32,32 @@ #ifdef HAVE_SW_VOLUME_CONTROL #include "pcm_sw_volume.h" -void audiohw_set_master_vol(int vol_l, int vol_r) +void audiohw_set_volume(int vol_l, int vol_r) { pcm_set_master_volume(vol_l, vol_r); } + #else /* ndef HAVE_SW_VOLUME_CONTROL */ + extern void pcm_set_mixer_volume(int); void audiohw_set_volume(int volume) { #if CONFIG_CODEC == SWCODEC -#if (CONFIG_PLATFORM & PLATFORM_MAEMO5) +#if !(CONFIG_PLATFORM & PLATFORM_MAEMO5) + if (volume < VOLUME_MIN) + volume = 0; + else + volume = SDL_MIX_MAXVOLUME * (volume - VOLUME_MIN + ONE_DB) / + (VOLUME_RANGE + ONE_DB); +#endif /* !(CONFIG_PLATFORM & PLATFORM_MAEMO5) */ + pcm_set_mixer_volume(volume); -#else - pcm_set_mixer_volume( - SDL_MIX_MAXVOLUME * ((volume - VOLUME_MIN) / 10) / (VOLUME_RANGE / 10)); -#endif /* (CONFIG_PLATFORM & PLATFORM_MAEMO5) */ -#else - (void)volume; #endif /* CONFIG_CODEC == SWCODEC */ + (void)volume; } #endif /* HAVE_SW_VOLUME_CONTROL */ -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}, -#if defined(HAVE_RECORDING) - [SOUND_LEFT_GAIN] = {"dB", 1, 1,-128, 96, 0}, - [SOUND_RIGHT_GAIN] = {"dB", 1, 1,-128, 96, 0}, - [SOUND_MIC_GAIN] = {"dB", 1, 1,-128, 108, 16}, -#endif -#if defined(AUDIOHW_HAVE_BASS_CUTOFF) - [SOUND_BASS_CUTOFF] = {"", 0, 1, 1, 4, 1}, -#endif -#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}, - [SOUND_MDB_STRENGTH] = {"dB", 0, 1, 0, 127, 48}, - [SOUND_MDB_HARMONICS] = {"%", 0, 1, 0, 100, 50}, - [SOUND_MDB_CENTER] = {"Hz", 0, 10, 20, 300, 60}, - [SOUND_MDB_SHAPE] = {"Hz", 0, 10, 50, 300, 90}, - [SOUND_MDB_ENABLE] = {"", 0, 1, 0, 1, 0}, - [SOUND_SUPERBASS] = {"", 0, 1, 0, 1, 0}, -#endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */ -}; - /** * stubs here, for the simulator **/ @@ -149,12 +74,14 @@ void audiohw_set_prescaler(int value) #if defined(AUDIOHW_HAVE_BALANCE) void audiohw_set_balance(int value) { (void)value; } #endif +#ifndef HAVE_SW_TONE_CONTROLS #if defined(AUDIOHW_HAVE_BASS) void audiohw_set_bass(int value) { (void)value; } #endif #if defined(AUDIOHW_HAVE_TREBLE) void audiohw_set_treble(int value) { (void)value; } #endif +#endif /* HAVE_SW_TONE_CONTROLS */ #if CONFIG_CODEC != SWCODEC void audiohw_set_channel(int value) { (void)value; } void audiohw_set_stereo_width(int value){ (void)value; } @@ -182,6 +109,10 @@ void audiohw_set_eq_band_width(unsigned int band, int value) void audiohw_set_depth_3d(int value) { (void)value; } #endif +#if defined(AUDIOHW_HAVE_LINEOUT) +void audiohw_set_lineout_volume(int vol_l, int vol_r) + { (void)vol_l; (void)vol_r; } +#endif void audiohw_close(void) {} diff --git a/firmware/drivers/audio/tlv320.c b/firmware/drivers/audio/tlv320.c index 6b96ed212f..23d2fea3a1 100644 --- a/firmware/drivers/audio/tlv320.c +++ b/firmware/drivers/audio/tlv320.c @@ -46,8 +46,8 @@ const struct sound_settings_info audiohw_settings[] = { #endif }; -/* convert tenth of dB volume (-840..0) to master volume register value */ -int tenthdb2master(int db) +/* convert tenth of dB volume (-73..6) to master volume register value */ +static int vol_tenthdb2hw(int db) { /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */ /* 1111111 == +6dB (0x7f) */ @@ -210,8 +210,11 @@ void audiohw_set_frequency(int fsel) * * Left & Right: 48 .. 121 .. 127 => Volume -73dB (mute) .. +0 dB .. +6 dB */ -void audiohw_set_headphone_vol(int vol_l, int vol_r) +void audiohw_set_volume(int vol_l, int vol_r) { + vol_l = vol_tenthdb2hw(vol_l); + vol_r = vol_tenthdb2hw(vol_r); + unsigned value_dap = tlv320_regs[REG_DAP]; unsigned value_dap_last = value_dap; unsigned value_l = LHV_LHV(vol_l); diff --git a/firmware/drivers/audio/tsc2100.c b/firmware/drivers/audio/tsc2100.c index 6479f84b34..41327ae3d7 100644 --- a/firmware/drivers/audio/tsc2100.c +++ b/firmware/drivers/audio/tsc2100.c @@ -29,18 +29,9 @@ #include "sound.h" #include "tsc2100.h" -const struct sound_settings_info audiohw_settings[] = { - [SOUND_VOLUME] = {"dB", 0, 1, VOLUME_MIN/10, VOLUME_MAX/10, -25}, - /* HAVE_SW_TONE_CONTROLS */ - [SOUND_BASS] = {"dB", 0, 1, -24, 24, 0}, - [SOUND_TREBLE] = {"dB", 0, 1, -24, 24, 0}, - [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, - [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, - [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, -}; static bool is_muted = false; -/* convert tenth of dB volume to master volume register value */ -int tenthdb2master(int db) +/* convert tenth of dB volume to volume register value */ +static int vol_tenthdb2hw(int db) { /* 0 to -63.0dB in 1dB steps, tsc2100 can goto -63.5 in 0.5dB steps */ if (db < VOLUME_MIN) { @@ -52,27 +43,6 @@ int tenthdb2master(int db) } } -int sound_val2phys(int setting, int value) -{ - int result; - - switch(setting) - { -#if 0 - case SOUND_LEFT_GAIN: - case SOUND_RIGHT_GAIN: - case SOUND_MIC_GAIN: - result = (value - 23) * 15; - break; -#endif - default: - result = value; - break; - } - - return result; -} - void audiohw_init(void) { short val = tsc2100_readreg(TSAC4_PAGE, TSAC4_ADDRESS); @@ -104,9 +74,12 @@ void audiohw_postinit(void) audiohw_mute(false); } -void audiohw_set_master_vol(int vol_l, int vol_r) +void audiohw_set_master_volume(int vol_l, int vol_r) { - tsc2100_writereg(TSDACGAIN_PAGE, TSDACGAIN_ADDRESS, (short)((vol_l<<8) | vol_r) ); + vol_l = vol_tenthdb2hw(vol_l); + vol_r = vol_tenthdb2hw(vol_r); + tsc2100_writereg(TSDACGAIN_PAGE, TSDACGAIN_ADDRESS, + (short)((vol_l<<8) | vol_r) ); } void audiohw_close(void) diff --git a/firmware/drivers/audio/uda1341.c b/firmware/drivers/audio/uda1341.c index 6b38353afe..ac3bcedb7d 100644 --- a/firmware/drivers/audio/uda1341.c +++ b/firmware/drivers/audio/uda1341.c @@ -28,23 +28,8 @@ #include "audiohw.h" - -const struct sound_settings_info audiohw_settings[] = { - [SOUND_VOLUME] = {"dB", 0, 1, -84, 0, -25}, - [SOUND_BASS] = {"dB", 0, 2, 0, 24, 0}, - [SOUND_TREBLE] = {"dB", 0, 2, 0, 6, 0}, - [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, /* not used */ - [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, /* not used */ - [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, /* not used */ -#ifdef HAVE_RECORDING - [SOUND_LEFT_GAIN] = {"dB", 1, 1,-128, 96, 0}, - [SOUND_RIGHT_GAIN] = {"dB", 1, 1,-128, 96, 0}, - [SOUND_MIC_GAIN] = {"dB", 1, 1,-128, 108, 16}, -#endif -}; - -/* convert tenth of dB volume (-600..0) to master volume register value */ -int tenthdb2master(int db) +/* convert tenth of dB volume (-600..0) to volume register value */ +static int vol_tenthdb2hw(int db) { if (db < -600) return 63; @@ -229,11 +214,12 @@ void audiohw_set_prescaler(int val) #endif /* AUDIOHW_HAVE_PRESCALER */ /** - * Sets left and right master volume (1(max) to 62(muted)) + * Set master volume (1(max) to 62(muted)) */ -void audiohw_set_master_vol(int vol_l, int vol_r) +void audiohw_set_volume(int volume) { - uda_regs[UDA_REG_ID_CTRL0] = (vol_l + vol_r) / 2; + volume = vol_tenthdb2hw(volume) / 2; + uda_regs[UDA_REG_ID_CTRL0] = volume; udacodec_write (UDA_REG_DATA0, UDA_DATA_CTRL0 | uda_regs[UDA_REG_ID_CTRL0]); } diff --git a/firmware/drivers/audio/uda1380.c b/firmware/drivers/audio/uda1380.c index fd32b398ca..9d6ece105b 100644 --- a/firmware/drivers/audio/uda1380.c +++ b/firmware/drivers/audio/uda1380.c @@ -40,22 +40,8 @@ #define USE_WSPLL #endif -const struct sound_settings_info audiohw_settings[] = { - [SOUND_VOLUME] = {"dB", 0, 1, -84, 0, -25}, - [SOUND_BASS] = {"dB", 0, 2, 0, 24, 0}, - [SOUND_TREBLE] = {"dB", 0, 2, 0, 6, 0}, - [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, - [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, - [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, -#ifdef HAVE_RECORDING - [SOUND_LEFT_GAIN] = {"dB", 1, 1,-128, 96, 0}, - [SOUND_RIGHT_GAIN] = {"dB", 1, 1,-128, 96, 0}, - [SOUND_MIC_GAIN] = {"dB", 1, 1,-128, 108, 16}, -#endif -}; - /* convert tenth of dB volume (-840..0) to master volume register value */ -int tenthdb2master(int db) +static int vol_tenthdb2hw(int db) { if (db < -720) /* 1.5 dB steps */ return (2940 - db) / 15; @@ -68,7 +54,7 @@ int tenthdb2master(int db) } /* convert tenth of dB volume (-780..0) to mixer volume register value */ -int tenthdb2mixer(int db) +static int mixer_tenthdb2hw(int db) { if (db < -660) /* 1.5 dB steps */ return (2640 - db) / 15; @@ -138,19 +124,12 @@ static int uda1380_write_reg(unsigned char reg, unsigned short value) /** * Sets left and right master volume (0(max) to 252(muted)) */ -void audiohw_set_master_vol(int vol_l, int vol_r) +void audiohw_set_volume(int vol_l, int vol_r) { + vol_l = vol_tenthdb2hw(vol_l); + vol_r = vol_tenthdb2hw(vol_r); uda1380_write_reg(REG_MASTER_VOL, - MASTER_VOL_LEFT(vol_l) | MASTER_VOL_RIGHT(vol_r)); -} - -/** - * Sets mixer volume for both channels (0(max) to 228(muted)) - */ -void audiohw_set_mixer_vol(int channel1, int channel2) -{ - uda1380_write_reg(REG_MIX_VOL, - MIX_VOL_CH_1(channel1) | MIX_VOL_CH_2(channel2)); + MASTER_VOL_LEFT(vol_l) | MASTER_VOL_RIGHT(vol_r)); } /** @@ -285,7 +264,9 @@ void audiohw_postinit(void) void audiohw_set_prescaler(int val) { - audiohw_set_mixer_vol(tenthdb2mixer(-val), tenthdb2mixer(-val)); + val = mixer_tenthdb2hw(-val); + uda1380_write_reg(REG_MIX_VOL, + MIX_VOL_CH_1(val) | MIX_VOL_CH_2(val)); } /* Nice shutdown of UDA1380 codec */ diff --git a/firmware/drivers/audio/wm8731.c b/firmware/drivers/audio/wm8731.c index 71050454f3..3689a28f31 100644 --- a/firmware/drivers/audio/wm8731.c +++ b/firmware/drivers/audio/wm8731.c @@ -37,22 +37,6 @@ #include "wmcodec.h" #include "sound.h" - -const struct sound_settings_info audiohw_settings[] = { - [SOUND_VOLUME] = {"dB", 0, 1, -74, 6, -25}, - /* HAVE_SW_TONE_CONTROLS */ - [SOUND_BASS] = {"dB", 0, 1, -24, 24, 0}, - [SOUND_TREBLE] = {"dB", 0, 1, -24, 24, 0}, - [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, - [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, - [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, -#if defined(HAVE_WM8731) && defined(HAVE_RECORDING) - [SOUND_LEFT_GAIN] = {"dB", 1, 1, 0, 31, 23}, - [SOUND_RIGHT_GAIN] = {"dB", 1, 1, 0, 31, 23}, - [SOUND_MIC_GAIN] = {"dB", 1, 1, 0, 1, 0}, -#endif -}; - /* Init values/shadows * Ignore bit 8 since that only specifies "both" for updating * gains - "RESET" (15h) not included */ @@ -109,22 +93,6 @@ static void wmc_write_masked(int reg, unsigned bits, unsigned mask) wmc_write(reg, (wmc_regs[reg] & ~mask) | (bits & mask)); } -/* convert tenth of dB volume (-730..60) to master volume register value */ -int tenthdb2master(int db) -{ - /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */ - /* 1111111 == +6dB (0x7f) */ - /* 1111001 == 0dB (0x79) */ - /* 0110000 == -73dB (0x30 */ - /* 0101111 == mute (0x2f) */ - - if (db < VOLUME_MIN) { - return 0x2f; - } else { - return((db/10)+0x30+73); - } -} - int sound_val2phys(int setting, int value) { int result; @@ -148,6 +116,21 @@ int sound_val2phys(int setting, int value) return result; } +/* convert tenth of dB volume (-730..60) to master volume register value */ +static int vol_tenthdb2hw(int db) +{ + /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */ + /* 1111111 == +6dB (0x7f) */ + /* 1111001 == 0dB (0x79) */ + /* 0110000 == -73dB (0x30) */ + /* 0101111 == mute (0x2f) */ + if (db < VOLUME_MIN) { + return 0x2f; + } else { + return((db/10)+0x30+73); + } +} + static void audiohw_mute(bool mute) { if (mute) { @@ -207,13 +190,11 @@ void audiohw_postinit(void) #endif } -void audiohw_set_master_vol(int vol_l, int vol_r) +void audiohw_set_volume(int vol_l, int vol_r) { /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */ - /* 1111111 == +6dB */ - /* 1111001 == 0dB */ - /* 0110000 == -73dB */ - /* 0101111 == mute (0x2f) */ + vol_l = vol_tenthdb2hw(vol_l); + vol_r = vol_tenthdb2hw(vol_r); wmc_write_masked(LOUTVOL, vol_l, WMC_OUT_VOL_MASK); wmc_write_masked(ROUTVOL, vol_r, WMC_OUT_VOL_MASK); } diff --git a/firmware/drivers/audio/wm8751.c b/firmware/drivers/audio/wm8751.c index 4cb85db436..feba05e504 100644 --- a/firmware/drivers/audio/wm8751.c +++ b/firmware/drivers/audio/wm8751.c @@ -32,35 +32,6 @@ #include "system.h" #include "sound.h" -const struct sound_settings_info audiohw_settings[] = { - [SOUND_VOLUME] = {"dB", 0, 1, -74, 6, -25}, - [SOUND_BASS] = {"dB", 1, 15, -60, 90, 0}, - [SOUND_TREBLE] = {"dB", 1, 15, -60, 90, 0}, - [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, - [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, - [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, -#ifdef HAVE_RECORDING - /* PGA -17.25dB to 30.0dB in 0.75dB increments 64 steps - * digital gain 0dB to 30.0dB in 0.5dB increments - * we use 0.75dB fake steps through whole range - * - * This combined gives -17.25 to 60.0dB - */ - [SOUND_LEFT_GAIN] = {"dB", 2, 75, -1725, 6000, 0}, - [SOUND_RIGHT_GAIN] = {"dB", 2, 75, -1725, 6000, 0}, - [SOUND_MIC_GAIN] = {"dB", 2, 75, -1725, 6000, 3000}, -#endif -#ifdef AUDIOHW_HAVE_BASS_CUTOFF - [SOUND_BASS_CUTOFF] = {"Hz", 0, 70, 130, 200, 200}, -#endif -#ifdef AUDIOHW_HAVE_TREBLE_CUTOFF - [SOUND_TREBLE_CUTOFF] = {"kHz", 0, 4, 4, 8, 4}, -#endif -#ifdef AUDIOHW_HAVE_DEPTH_3D - [SOUND_DEPTH_3D] = {"%", 0, 1, 0, 15, 0}, -#endif -}; - static uint16_t wmcodec_regs[WM_NUM_REGS] = { [0 ... WM_NUM_REGS-1] = 0x200, /* set invalid data in gaps */ @@ -139,7 +110,7 @@ static void wmcodec_set_masked(unsigned int reg, unsigned int val, } /* convert tenth of dB volume (-730..60) to master volume register value */ -int tenthdb2master(int db) +static int vol_tenthdb2hw(int db) { /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */ /* 1111111 == +6dB (0x7f) */ @@ -186,25 +157,6 @@ void audiohw_set_treble_cutoff(int val) } #endif - -int sound_val2phys(int setting, int value) -{ - int result; - - switch (setting) - { -#ifdef AUDIOHW_HAVE_DEPTH_3D - case SOUND_DEPTH_3D: - result = (100 * value + 8) / 15; - break; -#endif - default: - result = value; - } - - return result; -} - static void audiohw_mute(bool mute) { /* Mute: Set DACMU = 1 to soft-mute the audio DACs. */ @@ -335,40 +287,39 @@ void audiohw_postinit(void) #endif } -void audiohw_set_master_vol(int vol_l, int vol_r) +void audiohw_set_volume(int vol_l, int vol_r) { - /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */ - /* 1111111 == +6dB */ - /* 1111001 == 0dB */ - /* 0110000 == -73dB */ - /* 0101111 == mute (0x2f) */ - + vol_l = vol_tenthdb2hw(vol_l); + vol_r = vol_tenthdb2hw(vol_r); wmcodec_set_masked(LOUT1, LOUT1_LOUT1VOL(vol_l), LOUT1_LOUT1VOL_MASK); wmcodec_set_masked(ROUT1, ROUT1_RO1VU | ROUT1_ROUT1VOL(vol_r), ROUT1_ROUT1VOL_MASK); } -#ifdef TOSHIBA_GIGABEAT_F -void audiohw_set_lineout_vol(int vol_l, int vol_r) +#ifdef AUDIOHW_HAVE_LINEOUT +void audiohw_set_lineout_volume(int vol_l, int vol_r) { + vol_l = vol_tenthdb2hw(vol_l); + vol_r = vol_tenthdb2hw(vol_r); wmcodec_set_masked(LOUT2, LOUT2_LOUT2VOL(vol_l), LOUT2_LOUT2VOL_MASK); wmcodec_set_masked(ROUT2, ROUT2_RO2VU | ROUT2_ROUT2VOL(vol_r), ROUT2_ROUT2VOL_MASK); } -#endif +#endif /* AUDIOHW_HAVE_LINEOUT */ void audiohw_set_bass(int value) { - wmcodec_set_masked(BASSCTRL, - BASSCTRL_BASS(tone_tenthdb2hw(value)), + value = tone_tenthdb2hw(value); + wmcodec_set_masked(BASSCTRL, BASSCTRL_BASS(value), BASSCTRL_BASS_MASK); } void audiohw_set_treble(int value) { - wmcodec_set_masked(TREBCTRL, TREBCTRL_TREB(tone_tenthdb2hw(value)), + value = tone_tenthdb2hw(value); + wmcodec_set_masked(TREBCTRL, TREBCTRL_TREB(value), TREBCTRL_TREB_MASK); } diff --git a/firmware/drivers/audio/wm8758.c b/firmware/drivers/audio/wm8758.c index aa78a7710d..3e0c88c55c 100644 --- a/firmware/drivers/audio/wm8758.c +++ b/firmware/drivers/audio/wm8758.c @@ -33,22 +33,6 @@ #include "audiohw.h" #include "sound.h" -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}, -#ifdef HAVE_RECORDING - [SOUND_LEFT_GAIN] = {"dB", 1, 1, 0, 63, 16}, - [SOUND_RIGHT_GAIN] = {"dB", 1, 1, 0, 63, 16}, - [SOUND_MIC_GAIN] = {"dB", 1, 1, 0, 63, 16}, -#endif - [SOUND_BASS_CUTOFF] = {"", 0, 1, 1, 4, 1}, - [SOUND_TREBLE_CUTOFF] = {"", 0, 1, 1, 4, 1}, -}; - /* shadow registers */ static unsigned short eq1_reg = EQ1_EQ3DMODE | EQ_GAIN_VALUE(0); static unsigned short eq5_reg = EQ_GAIN_VALUE(0); @@ -96,27 +80,6 @@ static void get_volume_params(int db, int *dac, int *amp) } } -int sound_val2phys(int setting, int value) -{ - int result; - - switch(setting) - { -#ifdef HAVE_RECORDING - case SOUND_LEFT_GAIN: - case SOUND_RIGHT_GAIN: - case SOUND_MIC_GAIN: - result = ((value - 16) * 15) / 2; - break; -#endif - default: - result = value; - break; - } - - return result; -} - static void audiohw_mute(bool mute) { if (mute) { diff --git a/firmware/drivers/audio/wm8975.c b/firmware/drivers/audio/wm8975.c index c46dab79de..3b9fef0dbc 100644 --- a/firmware/drivers/audio/wm8975.c +++ b/firmware/drivers/audio/wm8975.c @@ -34,20 +34,6 @@ #include "wmcodec.h" #include "audiohw.h" -const struct sound_settings_info audiohw_settings[] = { - [SOUND_VOLUME] = {"dB", 0, 1, -74, 6, -25}, - [SOUND_BASS] = {"dB", 0, 1, -6, 9, 0}, - [SOUND_TREBLE] = {"dB", 0, 1, -6, 9, 0}, - [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, - [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, - [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, -#ifdef HAVE_RECORDING - [SOUND_LEFT_GAIN] = {"dB", 1, 1, 0, 63, 23}, - [SOUND_RIGHT_GAIN] = {"dB", 1, 1, 0, 63, 23}, - [SOUND_MIC_GAIN] = {"dB", 1, 1, 0, 63, 0}, -#endif -}; - static unsigned short wm8975_regs[WM8975_NUM_REGISTERS] = { [LINVOL] = LINVOL_LZCEN | 23, /* 0dB */ @@ -85,7 +71,7 @@ static void wm8975_write_or(int reg, unsigned bits) } /* convert tenth of dB volume (-730..60) to master volume register value */ -int tenthdb2master(int db) +static int vol_tenthdb2hw(int db) { /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */ /* 1111111 == +6dB (0x7f) */ @@ -100,29 +86,6 @@ int tenthdb2master(int db) } } -int sound_val2phys(int setting, int value) -{ - int result; - - switch(setting) - { -#ifdef HAVE_RECORDING - case SOUND_LEFT_GAIN: - case SOUND_RIGHT_GAIN: - result = ((value - 23) * 15) / 2; - break; - case SOUND_MIC_GAIN: - result = ((value - 23) * 15) / 2 + 200; - break; -#endif - default: - result = value; - break; - } - - return result; -} - static void audiohw_mute(bool mute) { if (mute) { @@ -205,13 +168,10 @@ void audiohw_postinit(void) } #endif -void audiohw_set_master_vol(int vol_l, int vol_r) +void audiohw_set_volume(int vol_l, int vol_r) { - /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */ - /* 1111111 == +6dB */ - /* 1111001 == 0dB */ - /* 0110000 == -73dB */ - /* 0101111 == mute (0x2f) */ + vol_l = vol_tenthdb2hw(vol_l); + vol_r = vol_tenthdb2hw(vol_r); /* OUT1 */ wm8975_write(LOUT1VOL, LOUT1VOL_LO1ZC | vol_l); @@ -220,6 +180,9 @@ void audiohw_set_master_vol(int vol_l, int vol_r) void audiohw_set_lineout_vol(int vol_l, int vol_r) { + vol_l = vol_tenthdb2hw(vol_l); + vol_r = vol_tenthdb2hw(vol_r); + /* OUT2 */ wm8975_write(LOUT2VOL, LOUT2VOL_LO2ZC | vol_l); wm8975_write(ROUT2VOL, ROUT2VOL_RO2VU | ROUT2VOL_RO2ZC | vol_r); diff --git a/firmware/drivers/audio/wm8978.c b/firmware/drivers/audio/wm8978.c index 3602bf9cb3..3a86ef204e 100644 --- a/firmware/drivers/audio/wm8978.c +++ b/firmware/drivers/audio/wm8978.c @@ -36,39 +36,6 @@ * file it may break things. */ extern void audiohw_enable_headphone_jack(bool enable); -const struct sound_settings_info audiohw_settings[] = -{ - [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}, -#if 0 - [SOUND_MIC_GAIN] = {"dB", 1, 1,-238, 16, 0}, -#endif -#endif -}; - static uint16_t wmc_regs[WMC_NUM_REGISTERS] = { /* Initialized with post-reset default values - the 2-wire interface @@ -184,9 +151,9 @@ static void wmc_write_masked(unsigned int reg, unsigned int bits, wmc_write(reg, (wmc_regs[reg] & ~mask) | (bits & mask)); } -/* convert tenth of dB volume (-890..60) to master volume register value +/* convert tenth of dB volume (-890..60) to volume register value * (000000...111111) */ -int tenthdb2master(int db) +static int vol_tenthdb2hw(int db) { /* -90dB to +6dB 1dB steps (96 levels) 7bits */ /* 1100000 == +6dB (0x60,96) */ @@ -194,7 +161,7 @@ int tenthdb2master(int db) /* 1000001 == -57dB (0x21,33,DAC) */ /* 0000001 == -89dB (0x01,01) */ /* 0000000 == -90dB (0x00,00,Mute) */ - if (db <= VOLUME_MIN) + if (db < VOLUME_MIN) { return 0x0; } @@ -204,39 +171,6 @@ int tenthdb2master(int db) } } -int sound_val2phys(int setting, int value) -{ - int result; - - switch (setting) - { -#ifdef HAVE_RECORDING - case SOUND_LEFT_GAIN: - case SOUND_RIGHT_GAIN: - case SOUND_MIC_GAIN: - result = value * 5; - break; -#endif - - case SOUND_EQ_BAND1_GAIN+0x10000: - case SOUND_EQ_BAND2_GAIN+0x10000: - case SOUND_EQ_BAND3_GAIN+0x10000: - case SOUND_EQ_BAND4_GAIN+0x10000: - case SOUND_EQ_BAND5_GAIN+0x10000: - result = value * 10; - break; - - case SOUND_DEPTH_3D: - result = (100 * value + 8) / 15; - break; - - default: - result = value; - } - - return result; -} - void audiohw_preinit(void) { /* 1. Turn on external power supplies. Wait for supply voltage to settle. */ @@ -350,13 +284,16 @@ static void sync_prescaler(void) WMC_DVOL); } -void audiohw_set_headphone_vol(int vol_l, int vol_r) +void audiohw_set_volume(int vol_l, int vol_r) { int prev_l = wmc_vol.vol_l; int prev_r = wmc_vol.vol_r; int dac_l, dac_r, hp_l, hp_r; int mix_l, mix_r, boost_l, boost_r; + vol_l = vol_tenthdb2hw(vol_l); + vol_r = vol_tenthdb2hw(vol_r); + wmc_vol.vol_l = vol_l; wmc_vol.vol_r = vol_r; diff --git a/firmware/drivers/audio/wm8985.c b/firmware/drivers/audio/wm8985.c index 06b3fa3b44..2d49e706c8 100644 --- a/firmware/drivers/audio/wm8985.c +++ b/firmware/drivers/audio/wm8985.c @@ -88,32 +88,12 @@ #define OUT4MIX 0x39 #define BIASCTL 0x3d -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}, -#ifdef HAVE_RECORDING - [SOUND_LEFT_GAIN] = {"dB", 1, 1,-128, 96, 0}, - [SOUND_RIGHT_GAIN] = {"dB", 1, 1,-128, 96, 0}, - [SOUND_MIC_GAIN] = {"dB", 1, 1,-128, 108, 16}, -#endif -#ifdef AUDIOHW_HAVE_BASS_CUTOFF - [SOUND_BASS_CUTOFF] = {"", 0, 1, 1, 4, 1}, -#endif -#ifdef AUDIOHW_HAVE_TREBLE_CUTOFF - [SOUND_TREBLE_CUTOFF] = {"", 0, 1, 1, 4, 1}, -#endif -}; - /* shadow registers */ static unsigned int eq1_reg; static unsigned int eq5_reg; /* convert tenth of dB volume (-89..6) to master volume register value */ -int tenthdb2master(int db) +static int vol_tenthdb2hw(int db) { /* Might have no sense, taken from wm8758.c : att DAC AMP result @@ -216,9 +196,13 @@ void audiohw_postinit(void) audiohw_mute(0); } -void audiohw_set_headphone_vol(int vol_l, int vol_r) +void audiohw_set_volume(int vol_l, int vol_r) { int dac_l, amp_l, dac_r, amp_r; + + vol_l = vol_tenthdb2hw(vol_l); + vol_r = vol_tenthdb2hw(vol_r); + get_volume_params(vol_l, &dac_l, &_l); get_volume_params(vol_r, &dac_r, &_r); @@ -232,15 +216,19 @@ void audiohw_set_headphone_vol(int vol_l, int vol_r) wmcodec_write(ROUT1VOL, amp_r | 0x180); } -void audiohw_set_lineout_vol(int vol_l, int vol_r) +void audiohw_set_lineout_volume(int vol_l, int vol_r) { - int dac_l, amp_l, dac_r, amp_r; - get_volume_params(vol_l, &dac_l, &_l); - get_volume_params(vol_r, &dac_r, &_r); + int dac_l, amp_l, dac_r, amp_r; + + vol_l = vol_tenthdb2hw(vol_l); + vol_r = vol_tenthdb2hw(vol_r); + + get_volume_params(vol_l, &dac_l, &_l); + get_volume_params(vol_r, &dac_r, &_r); - /* set lineout amp OUT2 */ - wmcodec_write(LOUT2VOL, amp_l); - wmcodec_write(ROUT2VOL, amp_r | 0x100); + /* set lineout amp OUT2 */ + wmcodec_write(LOUT2VOL, amp_l); + wmcodec_write(ROUT2VOL, amp_r | 0x100); } void audiohw_set_aux_vol(int vol_l, int vol_r) diff --git a/firmware/export/aic3x.h b/firmware/export/aic3x.h index 4cfa0a5535..65e1ebd62c 100644 --- a/firmware/export/aic3x.h +++ b/firmware/export/aic3x.h @@ -25,12 +25,10 @@ #define VOLUME_MIN -630 #define VOLUME_MAX 0 -extern int tenthdb2master(int db); +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -64, 0, -25) /*** definitions ***/ -extern void audiohw_set_headphone_vol(int vol_l, int vol_r); - -extern void aic3x_switch_output(bool stereo); +void aic3x_switch_output(bool stereo); /* Page 0 registers */ #define AIC3X_PAGE_SELECT 0 diff --git a/firmware/export/ak4537.h b/firmware/export/ak4537.h index 1f272d41fc..abf2a378ae 100644 --- a/firmware/export/ak4537.h +++ b/firmware/export/ak4537.h @@ -26,9 +26,7 @@ #define VOLUME_MIN -1270 #define VOLUME_MAX 0 -extern int tenthdb2master(int db); - -extern void audiohw_set_master_vol(int vol_l, int vol_r); +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -128, 0, -25) #define AKC_NUM_REGS 0x11 diff --git a/firmware/export/as3514.h b/firmware/export/as3514.h index 85da14493f..e9e48fab63 100644 --- a/firmware/export/as3514.h +++ b/firmware/export/as3514.h @@ -24,11 +24,32 @@ #include "config.h" -extern int tenthdb2master(int db); +#if 0 +#define AUDIOHW_CAPS (LINEOUT_CAP | LIN_GAIN_CAP | MIC_GAIN_CAP) +#endif -extern void audiohw_set_master_vol(int vol_l, int vol_r); -extern void audiohw_set_lineout_vol(int vol_l, int vol_r); -extern void audiohw_set_sampr_dividers(int fsel); +#define AUDIOHW_CAPS (LIN_GAIN_CAP | MIC_GAIN_CAP) + +/*different volume ranges for different AMS chips*/ +#if CONFIG_CPU == AS3525v2 +/* Headphone volume goes from -81.0 ... +6dB */ +#define VOLUME_MIN -810 +#define VOLUME_MAX 60 +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -82, 6, -25) +#else /* AS3525v1 */ +/* Headphone volume goes from -73.5 ... +6dB */ +#define VOLUME_MIN -735 +#define VOLUME_MAX 60 +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -74, 6, -25) +#endif /* CONFIG_CPU == AS3525v2 */ + +#ifdef HAVE_RECORDING +AUDIOHW_SETTING(MIC_GAIN, "dB", 1, 1, 0, 39, 23, (val - 23) * 15) +AUDIOHW_SETTING(LEFT_GAIN, "dB", 1, 1, 0, 31, 23, (val - 23) * 15) +AUDIOHW_SETTING(RIGHT_GAIN, "dB", 1, 1, 0, 31, 23, (val - 23) * 15) +#endif /* HAVE_RECORDING */ + +void audiohw_set_sampr_dividers(int fsel); /* Register Descriptions */ @@ -126,16 +147,6 @@ extern void audiohw_set_sampr_dividers(int fsel); #define AS3514_UID_LEN 16 #endif -/*different volume ranges for different AMS chips*/ -#if CONFIG_CPU == AS3525v2 -/* Headphone volume goes from -81.0 ... +6dB */ -#define VOLUME_MIN -810 -#else -/* Headphone volume goes from -73.5 ... +6dB */ -#define VOLUME_MIN -735 -#endif -#define VOLUME_MAX 60 - /*** Audio Registers ***/ /* 00h (LINE_OUT_R) to 16h (AUDIOSET3) */ diff --git a/firmware/export/audiohw.h b/firmware/export/audiohw.h index 304c5aa460..e18e996282 100644 --- a/firmware/export/audiohw.h +++ b/firmware/export/audiohw.h @@ -35,6 +35,35 @@ #define TREBLE_CUTOFF_CAP (1 << 6) #define EQ_CAP (1 << 7) #define DEPTH_3D_CAP (1 << 8) +#define LINEOUT_CAP (1 << 9) +#define MONO_VOL_CAP (1 << 10) +#define LIN_GAIN_CAP (1 << 11) +#define MIC_GAIN_CAP (1 << 12) + +/* Used by every driver to export its min/max/default values for its audio + settings. */ +#ifdef AUDIOHW_IS_SOUND_C +/* This is the master file with the settings table... */ +struct sound_settings_info +{ + const char *unit; + char numdecimals; + char steps; + short minval; + short maxval; + short defaultval; +}; + +#define AUDIOHW_SETTING(name, us, nd, st, minv, maxv, defv, expr...) \ + static const struct sound_settings_info _audiohw_setting_##name = \ + { .unit = us, .numdecimals = nd, .steps = st, \ + .minval = minv, .maxval = maxv, .defaultval = defv }; \ + static inline int _sound_val2phys_##name(int val) \ + { return #expr[0] ? expr : val; } +#else +/* ...otherwise these produce nothing. */ +#define AUDIOHW_SETTING(name, us, nd, st, minv, maxv, defv, expr...) +#endif #ifdef HAVE_UDA1380 #include "uda1380.h" @@ -78,17 +107,25 @@ #include "imx233-codec.h" #elif defined(HAVE_DUMMY_CODEC) #include "dummy_codec.h" -#endif -#if (CONFIG_PLATFORM & (PLATFORM_ANDROID|PLATFORM_MAEMO|PLATFORM_PANDORA|PLATFORM_SDL)) -/* #include gives errors in other code areas, - * we don't really need it here, so don't. but it should maybe be fixed */ -#ifndef SIMULATOR /* simulator gets values from the target .h files */ -#define VOLUME_MIN -990 -#define VOLUME_MAX 0 -#endif +#elif (CONFIG_PLATFORM & (PLATFORM_ANDROID | PLATFORM_MAEMO\ + | PLATFORM_PANDORA | PLATFORM_SDL)) +#include "hosted_codec.h" #endif +#if defined(SIMULATOR) && !defined(HAVE_SW_VOLUME_CONTROL) +/* For now, without software volume control, sim only supports mono control */ +#define AUDIOHW_HAVE_MONO_VOLUME +#endif +/* Some values are the same for every codec and can be defined here one + time. */ +#ifdef HAVE_SW_TONE_CONTROLS +AUDIOHW_SETTING(BASS, "dB", 0, 1, -24, 24, 0) +AUDIOHW_SETTING(TREBLE, "dB", 0, 1, -24, 24, 0) +#endif /* HAVE_SW_TONE_CONTROLS */ +AUDIOHW_SETTING(BALANCE, "%", 0, 1, -100, 100, 0) +AUDIOHW_SETTING(CHANNELS, "", 0, 1, 0, 5, 0) +AUDIOHW_SETTING(STEREO_WIDTH, "%", 0, 5, 0, 250, 100) #define ONE_DB 10 @@ -246,7 +283,26 @@ enum AUDIOHW_EQ_SETTINGS #if (AUDIOHW_CAPS & DEPTH_3D_CAP) #define AUDIOHW_HAVE_DEPTH_3D #endif -#else + +#if (AUDIOHW_CAPS & LINEOUT_CAP) +#define AUDIOHW_HAVE_LINEOUT +#endif + +#if (AUDIOHW_CAPS & MONO_VOL_CAP) +#define AUDIOHW_HAVE_MONO_VOLUME +#endif + +#ifdef HAVE_RECORDING +#if (AUDIOHW_CAPS & LIN_GAIN_CAP) +#define AUDIOHW_HAVE_LIN_GAIN +#endif + +#if (AUDIOHW_CAPS & MIC_GAIN_CAP) +#define AUDIOHW_HAVE_MIC_GAIN +#endif +#endif /* HAVE_RECORDING */ + +#else /* ndef AUDIOHW_CAPS */ #if defined (HAVE_SW_TONE_CONTROLS) /* Needed for proper sound support */ #define AUDIOHW_HAVE_BASS @@ -255,6 +311,7 @@ enum AUDIOHW_EQ_SETTINGS #endif /* AUDIOHW_CAPS */ enum { + /* TODO: Volume shouldn't be needed if device doesn't have digital control */ SOUND_VOLUME = 0, /* Tone control */ #if defined(AUDIOHW_HAVE_BASS) @@ -276,9 +333,11 @@ enum { SOUND_MDB_ENABLE, SOUND_SUPERBASS, #endif -#if defined(HAVE_RECORDING) +#if defined(AUDIOHW_HAVE_LIN_GAIN) SOUND_LEFT_GAIN, SOUND_RIGHT_GAIN, +#endif +#if defined(AUDIOHW_HAVE_MIC_GAIN) SOUND_MIC_GAIN, #endif /* Bass and treble tone controls */ @@ -339,7 +398,8 @@ enum { SOUND_LAST_SETTING, /* Keep this last */ }; -enum Channel { +enum Channel +{ SOUND_CHAN_STEREO, SOUND_CHAN_MONO, SOUND_CHAN_CUSTOM, @@ -349,19 +409,6 @@ enum Channel { SOUND_CHAN_NUM_MODES, }; -struct sound_settings_info { - const char *unit; - char numdecimals; - char steps; - short minval; - short maxval; - short defaultval; -}; - -/* This struct is used by every driver to export its min/max/default values for - * its audio settings. Keep in mind that the order must be correct! */ -extern const struct sound_settings_info audiohw_settings[]; - /* All usable functions implemented by a audio codec drivers. Most of * the function in sound settings are only called, when in audio codecs * .h file suitable defines are added. @@ -390,17 +437,35 @@ void audiohw_postinit(void); */ void audiohw_close(void); -#if defined(AUDIOHW_HAVE_CLIPPING) || defined(HAVE_SDL_AUDIO) || defined(ANDROID) - /** +#ifdef AUDIOHW_HAVE_MONO_VOLUME + /** * Set new volume value * @param val to set. * NOTE: AUDIOHW_CAPS need to contain * CLIPPING_CAP */ void audiohw_set_volume(int val); +#else /* Stereo volume */ +/** + * Set new voluem value for each channel + * @param vol_l sets left channel volume + * @param vol_r sets right channel volume + */ +void audiohw_set_volume(int vol_l, int vol_r); +#endif /* AUDIOHW_HAVE_MONO_VOLUME */ + +#ifdef AUDIOHW_HAVE_LINEOUT + /** + * Set new voluem value for each channel + * @param vol_l sets left channel volume + * @param vol_r sets right channel volume + */ +void audiohw_set_lineout_volume(int vol_l, int vol_r); #endif -#ifdef AUDIOHW_HAVE_PRESCALER +#ifndef AUDIOHW_HAVE_CLIPPING +#if defined(AUDIOHW_HAVE_BASS) || defined(AUDIOHW_HAVE_TREBLE) \ + || defined(AUDIOHW_HAVE_EQ) /** * Set new prescaler value. * @param val to set. @@ -409,6 +474,7 @@ void audiohw_set_volume(int val); */ void audiohw_set_prescaler(int val); #endif +#endif /* !AUDIOHW_HAVE_CLIPPING */ #ifdef AUDIOHW_HAVE_BALANCE /** @@ -552,31 +618,38 @@ void audiohw_set_recvol(int left, int right, int type); void audiohw_set_monitor(bool enable); #endif - - -#if CONFIG_CODEC != SWCODEC - -/* functions which are only used by mas35xx codecs, but are also - aviable on SWCODECS through dsp */ - /** * Set channel configuration. * @param val new channel value (see enum Channel). */ void audiohw_set_channel(int val); +#ifdef HAVE_PITCHCONTROL +/** + * Set the pitch ratio + * @param ratio to set in .01% units + */ +void audiohw_set_pitch(int32_t val); + +/** + * Return the set pitch ratio + */ +int32_t audiohw_get_pitch(void); +#endif /* HAVE_PITCHCONTROL */ + /** * Set stereo width. * @param val new stereo width value. */ void audiohw_set_stereo_width(int val); -#endif /* CONFIG_CODEC != SWCODEC */ - #ifdef HAVE_SPEAKER - void audiohw_enable_speaker(bool on); - #endif /* HAVE_SPEAKER */ +#if CONFIG_CODEC == SWCODEC +typedef int (*audiohw_swcodec_cb_type)(int msg, intptr_t param); +void audiohw_swcodec_set_callback(audiohw_swcodec_cb_type func); +#endif /* CONFIG_CODEC == SWCODEC */ + #endif /* _AUDIOHW_H_ */ diff --git a/firmware/export/audiohw_settings.h b/firmware/export/audiohw_settings.h new file mode 100644 index 0000000000..8efbc0dbe7 --- /dev/null +++ b/firmware/export/audiohw_settings.h @@ -0,0 +1,143 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2005 by Linus Nielsen Feltzing + * Copyright (C) 2007 by Christian Gmeiner + * Copyright (C) 2013 by 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. + * + ****************************************************************************/ +#if defined(AUDIOHW_SOUND_SETTINGS_ENTRIES) +/* Define sound_setting_entries table */ + +#define AUDIOHW_SETTINGS(...) \ + static const struct sound_setting_entry \ + { \ + const struct sound_settings_info *info; \ + sound_set_type *function; \ + } sound_setting_entries[] = \ + { \ + [0 ... SOUND_LAST_SETTING-1] = { NULL, NULL }, \ + __VA_ARGS__ \ + }; + +#define AUDIOHW_SETTING_ENT(name, fn) \ + [SOUND_##name] = { .info = &_audiohw_setting_##name, .function = fn }, + +#elif defined(AUDIOHW_SOUND_SETTINGS_VAL2PHYS) + +/* Implements sound_val2phys */ +#define AUDIOHW_SETTINGS(...) \ + int sound_val2phys(int setting, int value) \ + { \ + switch (setting) \ + { \ + __VA_ARGS__ \ + default: \ + return value; \ + } \ + } + +#define AUDIOHW_SETTING_ENT(name, fn) \ + case SOUND_##name: return _sound_val2phys_##name(value); + +#endif /* setting table type selection */ + +AUDIOHW_SETTINGS( + /* TODO: Volume shouldn't be needed if device doesn't have digital + control */ + AUDIOHW_SETTING_ENT(VOLUME, sound_set_volume) +#if defined(AUDIOHW_HAVE_BASS) + AUDIOHW_SETTING_ENT(BASS, sound_set_bass) +#endif +#if defined(AUDIOHW_HAVE_TREBLE) + AUDIOHW_SETTING_ENT(TREBLE, sound_set_treble) +#endif + AUDIOHW_SETTING_ENT(BALANCE, sound_set_balance) + AUDIOHW_SETTING_ENT(CHANNELS, sound_set_channels) + AUDIOHW_SETTING_ENT(STEREO_WIDTH, sound_set_stereo_width) +#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) + AUDIOHW_SETTING_ENT(LOUDNESS, sound_set_loudness) + AUDIOHW_SETTING_ENT(AVC, sound_set_avc) + AUDIOHW_SETTING_ENT(MDB_STRENGTH, sound_set_mdb_strength) + AUDIOHW_SETTING_ENT(MDB_HARMONICS, sound_set_mdb_harmonics) + AUDIOHW_SETTING_ENT(MDB_CENTER, sound_set_mdb_center) + AUDIOHW_SETTING_ENT(MDB_SHAPE, sound_set_mdb_shape) + AUDIOHW_SETTING_ENT(MDB_ENABLE, sound_set_mdb_enable) + AUDIOHW_SETTING_ENT(SUPERBASS, sound_set_superbass) +#endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */ +#if defined(AUDIOHW_HAVE_LIN_GAIN) + AUDIOHW_SETTING_ENT(LEFT_GAIN, NULL) + AUDIOHW_SETTING_ENT(RIGHT_GAIN, NULL) +#endif +#if defined(AUDIOHW_HAVE_MIC_GAIN) + AUDIOHW_SETTING_ENT(MIC_GAIN, NULL) +#endif +#if defined(AUDIOHW_HAVE_BASS_CUTOFF) + AUDIOHW_SETTING_ENT(BASS_CUTOFF, sound_set_bass_cutoff) +#endif +#if defined(AUDIOHW_HAVE_TREBLE_CUTOFF) + AUDIOHW_SETTING_ENT(TREBLE_CUTOFF, sound_set_treble_cutoff) +#endif +#if defined(AUDIOHW_HAVE_DEPTH_3D) + AUDIOHW_SETTING_ENT(DEPTH_3D, sound_set_depth_3d) +#endif +/* Hardware EQ tone controls */ +#if defined(AUDIOHW_HAVE_EQ) + AUDIOHW_SETTING_ENT(EQ_BAND1_GAIN, sound_set_hw_eq_band1_gain) +#if defined(AUDIOHW_HAVE_EQ_BAND1_FREQUENCY) + AUDIOHW_SETTING_ENT(EQ_BAND1_FREQUENCY, sound_set_hw_eq_band1_frequency) +#endif +#if defined(AUDIOHW_HAVE_EQ_BAND2) + AUDIOHW_SETTING_ENT(EQ_BAND2_GAIN, sound_set_hw_eq_band2_gain) +#if defined(AUDIOHW_HAVE_EQ_BAND2_FREQUENCY) + AUDIOHW_SETTING_ENT(EQ_BAND2_FREQUENCY, sound_set_hw_eq_band2_frequency) +#endif +#if defined(AUDIOHW_HAVE_EQ_BAND2_WIDTH) + AUDIOHW_SETTING_ENT(EQ_BAND2_WIDTH, sound_set_hw_eq_band2_width) +#endif +#endif /* AUDIOHW_HAVE_EQ_BAND2 */ +#if defined(AUDIOHW_HAVE_EQ_BAND3) + AUDIOHW_SETTING_ENT(EQ_BAND3_GAIN, sound_set_hw_eq_band3_gain) +#if defined(AUDIOHW_HAVE_EQ_BAND3_FREQUENCY) + AUDIOHW_SETTING_ENT(EQ_BAND3_FREQUENCY, sound_set_hw_eq_band3_frequency) +#endif +#if defined(AUDIOHW_HAVE_EQ_BAND3_WIDTH) + AUDIOHW_SETTING_ENT(EQ_BAND3_WIDTH, sound_set_hw_eq_band3_width) +#endif +#endif /* AUDIOHW_HAVE_EQ_BAND3 */ +#if defined(AUDIOHW_HAVE_EQ_BAND4) + AUDIOHW_SETTING_ENT(EQ_BAND4_GAIN, sound_set_hw_eq_band4_gain) +#if defined(AUDIOHW_HAVE_EQ_BAND4_FREQUENCY) + AUDIOHW_SETTING_ENT(EQ_BAND4_FREQUENCY, sound_set_hw_eq_band4_frequency) +#endif +#if defined(AUDIOHW_HAVE_EQ_BAND4_WIDTH) + AUDIOHW_SETTING_ENT(EQ_BAND4_WIDTH, sound_set_hw_eq_band4_width) +#endif +#endif /* AUDIOHW_HAVE_EQ_BAND4 */ +#if defined(AUDIOHW_HAVE_EQ_BAND5) + AUDIOHW_SETTING_ENT(EQ_BAND5_GAIN, sound_set_hw_eq_band5_gain) +#if defined(AUDIOHW_HAVE_EQ_BAND5_FREQUENCY) + AUDIOHW_SETTING_ENT(EQ_BAND5_FREQUENCY, sound_set_hw_eq_band5_frequency) +#endif +#endif /* AUDIOHW_HAVE_EQ_BAND5 */ +#endif /* AUDIOHW_HAVE_EQ */ +); /* AUDIOHW_SETTINGS */ + +#undef AUDIOHW_SETTINGS +#undef AUDIOHW_SETTING_ENT +#undef AUDIOHW_SOUND_SETTINGS_ENTRIES +#undef AUDIOHW_SOUND_SETTINGS_VAL2PHYS diff --git a/firmware/export/cs42l55.h b/firmware/export/cs42l55.h index 86b54ef272..4584706dfd 100644 --- a/firmware/export/cs42l55.h +++ b/firmware/export/cs42l55.h @@ -26,14 +26,16 @@ #define VOLUME_MIN -580 #define VOLUME_MAX 120 -#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP | BASS_CUTOFF_CAP \ - | TREBLE_CUTOFF_CAP | PRESCALER_CAP) +#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP | BASS_CUTOFF_CAP | \ + TREBLE_CUTOFF_CAP | PRESCALER_CAP | LINEOUT_CAP) -extern int tenthdb2master(int db); +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -60, 12, -25) +AUDIOHW_SETTING(BASS, "dB", 1, 15,-105, 120, 0) +AUDIOHW_SETTING(TREBLE, "dB", 1, 15,-105, 120, 0) +AUDIOHW_SETTING(BASS_CUTOFF, "", 0, 1, 1, 4, 2) +AUDIOHW_SETTING(TREBLE_CUTOFF, "", 0, 1, 1, 4, 1) -extern void audiohw_set_master_vol(int vol_l, int vol_r); -extern void audiohw_set_lineout_vol(int vol_l, int vol_r); -extern void audiohw_enable_lineout(bool enable); +void audiohw_enable_lineout(bool enable); /* Register addresses and bits */ @@ -480,5 +482,4 @@ extern void audiohw_enable_lineout(bool enable); #define HIDDEN3F 0x3f #define HIDDEN3F_DEFAULT 0x46 - #endif /* __CS42L55_H__ */ diff --git a/firmware/export/dac3550a.h b/firmware/export/dac3550a.h index 23c4db9cbc..50bf922e90 100644 --- a/firmware/export/dac3550a.h +++ b/firmware/export/dac3550a.h @@ -37,7 +37,6 @@ #define DAC_GCFG 3 /* function prototypes */ -extern int tenthdb2reg(int db); extern int dac_volume(unsigned int left, unsigned int right, bool deemph); extern void dac_enable(bool enable); extern void dac_line_in(bool enable); diff --git a/firmware/export/dummy_codec.h b/firmware/export/dummy_codec.h index 122b55ef2f..90fd7b03c2 100644 --- a/firmware/export/dummy_codec.h +++ b/firmware/export/dummy_codec.h @@ -25,6 +25,6 @@ #define VOLUME_MIN -730 #define VOLUME_MAX 0 -void audiohw_set_master_vol(int vol_l, int vol_r); +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, VOLUME_MIN/10, VOLUME_MAX/10, 0) #endif /* __DUMMY_CODEC_H_ */ diff --git a/firmware/export/hosted_codec.h b/firmware/export/hosted_codec.h new file mode 100644 index 0000000000..50d1281394 --- /dev/null +++ b/firmware/export/hosted_codec.h @@ -0,0 +1,30 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 by Thomas Martitz + * + * 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. + * + ****************************************************************************/ +#ifndef HOSTED_CODEC_H +#define HOSTED_CODEC_H + +#define VOLUME_MIN -990 +#define VOLUME_MAX 0 + +#define AUDIOHW_CAPS (MONO_VOL_CAP) +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -100, 0, 0) + +#endif /* HOSTED_CODEC_H */ \ No newline at end of file diff --git a/firmware/export/imx233-codec.h b/firmware/export/imx233-codec.h index 6c329ccd1a..2fbd8bde59 100644 --- a/firmware/export/imx233-codec.h +++ b/firmware/export/imx233-codec.h @@ -27,10 +27,19 @@ #define VOLUME_MIN -1000 #define VOLUME_MAX 60 -#define AUDIOHW_CAPS (DEPTH_3D_CAP | BASS_CAP | TREBLE_CAP) +#define AUDIOHW_CAPS (DEPTH_3D_CAP | BASS_CAP | TREBLE_CAP | \ + LIN_GAIN_CAP | MIC_GAIN_CAP) /* Work with half dB since the i.MX233 doesn't have a better resolution */ -int tenthdb2master(int tdb); -void audiohw_set_headphone_vol(int vol_l, int vol_r); + +/* i.MX233 has half dB steps */ +AUDIOHW_SETTING(VOLUME, "dB", 0, 1,-101, 6, -25) +/* HAVE_SW_TONE_CONTROLS */ +#ifdef HAVE_RECORDING +AUDIOHW_SETTING(LEFT_GAIN, "dB", 1, 1, 0, 31, 23) +AUDIOHW_SETTING(RIGHT_GAIN, "dB", 1, 1, 0, 31, 23) +AUDIOHW_SETTING(MIC_GAIN, "dB", 1, 1, 0, 1, 1) +#endif /* HAVE_RECORDING */ +AUDIOHW_SETTING(DEPTH_3D, "%", 0, 1, 0, 15, 0) #endif /* __IMX233_CODEC_H_ */ diff --git a/firmware/export/jz4740-codec.h b/firmware/export/jz4740-codec.h index 3c088f5bf7..fc731fdf50 100644 --- a/firmware/export/jz4740-codec.h +++ b/firmware/export/jz4740-codec.h @@ -24,6 +24,17 @@ #define VOLUME_MIN -730 #define VOLUME_MAX 60 -void audiohw_set_master_vol(int vol_l, int vol_r); +/* TODO */ +#ifdef HAVE_SW_VOLUME_CONTROL +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -74, 6, -25) +#else +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, 0, 6, 0) +#endif /* HAVE_SW_VOLUME_CONTROL */ + +#ifdef HAVE_RECORDING +AUDIOHW_SETTING(LEFT_GAIN, "dB", 1, 1, 0, 31, 23) +AUDIOHW_SETTING(RIGHT_GAIN, "dB", 1, 1, 0, 31, 23) +AUDIOHW_SETTING(MIC_GAIN, "dB", 1, 1, 0, 1, 1) +#endif /* HAVE_RECORDING */ #endif /* __JZ4740_CODEC_H_ */ diff --git a/firmware/export/mas35xx.h b/firmware/export/mas35xx.h index f75658fce1..7643e0efdc 100644 --- a/firmware/export/mas35xx.h +++ b/firmware/export/mas35xx.h @@ -39,6 +39,14 @@ #if CONFIG_CODEC == MAS3507D +#define VOLUME_MIN -780 +#define VOLUME_MAX 180 +#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP | PRESCALER_CAP) + +AUDIOHW_SETTING(SOUND_VOLUME, "dB", 0, 1, -78, 18, -18) +AUDIOHW_SETTING(SOUND_BASS, "dB", 0, 1, -15, 15, 7) +AUDIOHW_SETTING(SOUND_TREBLE, "dB", 0, 1, -15, 15, 7) + /* I2C defines */ #define MAS_ADR 0x3a #define MAS_DEV_WRITE (MAS_ADR | 0x00) @@ -71,10 +79,6 @@ #define MAS_D0_OUT_RL 0x7fa #define MAS_D0_OUT_RR 0x7fb -#define VOLUME_MIN -780 -#define VOLUME_MAX 180 -#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP | PRESCALER_CAP) - static const unsigned int bass_table[] = { 0x9e400, /* -15dB */ @@ -167,6 +171,36 @@ static const unsigned int prescale_table[] = #else /* CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F */ +#define VOLUME_MIN -400 +#define VOLUME_MAX 600 + +AUDIOHW_SETTING(VOLUME, "dB", 0, 1,-100, 12, -25) +AUDIOHW_SETTING(BASS, "dB", 0, 1, -12, 12, 6) +AUDIOHW_SETTING(TREBLE, "dB", 0, 1, -12, 12, 6) +AUDIOHW_SETTING(LOUDNESS, "dB", 0, 1, 0, 17, 0) +AUDIOHW_SETTING(AVC "", 0, 1, -1, 4, 0) +AUDIOHW_SETTING(MDB_STRENGTH, "dB", 0, 1, 0, 127, 48) +AUDIOHW_SETTING(MDB_HARMONICS, "%", 0, 1, 0, 100, 50) +AUDIOHW_SETTING(MDB_CENTER "Hz", 0, 10, 20, 300, 60) +AUDIOHW_SETTING(MDB_SHAPE "Hz", 0, 10, 50, 300, 90) +AUDIOHW_SETTING(MDB_ENABLE "", 0, 1, 0, 1, 0) +AUDIOHW_SETTING(SUPERBASS "", 0, 1, 0, 1, 0) + +#if CONFIG_CODEC == MAS3587F && defined(HAVE_RECORDING) +/* MAS3587F and MAS3539F handle clipping prevention internally so we do not + * need the prescaler -> CLIPPING_CAP */ +#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP | BALANCE_CAP | CLIPPING_CAP | \ + MONO_VOL_CAP | LIN_GAIN_CAP | MIC_GAIN_CAP) +AUDIOHW_SETTING(LEFT_GAIN, "dB", 1, 1, 0, 15, 8, (val - 2) * 15) +AUDIOHW_SETTING(RIGHT_GAIN, "dB", 1, 1, 0, 15, 8, (val - 2) * 15) +AUDIOHW_SETTING(MIC_GAIN, "dB", 1, 1, 0, 15, 2, val * 15 + 210) +#else +/* MAS3587F and MAS3539F handle clipping prevention internally so we do not + * need the prescaler -> CLIPPING_CAP */ +#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP | BALANCE_CAP | CLIPPING_CAP | \ + MONO_VOL_CAP) +#endif /* MAS3587F && HAVE_RECORDING */ + /* I2C defines */ #define MAS_ADR 0x3c #define MAS_DEV_WRITE (MAS_ADR | 0x00) @@ -248,18 +282,7 @@ static const unsigned int prescale_table[] = #define MAS_D0_CRC_ERROR_COUNT 0xfd3 #endif -/* MAS3587F and MAS3539F handle clipping prevention internally so we do not need - * the prescaler -> CLIPPING_CAP - */ - -#define VOLUME_MIN -400 -#define VOLUME_MAX 600 -#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP | BALANCE_CAP | CLIPPING_CAP) - -#endif /* CONFIG_CODEC */ - /* Function prototypes */ -#if CONFIG_CODEC == MAS3587F || CONFIG_CODEC == MAS3539F extern void audiohw_set_loudness(int value); extern void audiohw_set_avc(int value); extern void audiohw_set_mdb_strength(int value); @@ -269,7 +292,9 @@ extern void audiohw_set_mdb_shape(int value); extern void audiohw_set_mdb_enable(int value); extern void audiohw_set_superbass(int value); extern void audiohw_set_balance(int val); -extern void audiohw_set_pitch(unsigned long val); -#endif +extern void audiohw_set_pitch(int32_t val); +extern int audiohw_get_pitch(void); + +#endif /* CONFIG_CODEC */ #endif /* _MAS35XX_H */ diff --git a/firmware/export/rk27xx_codec.h b/firmware/export/rk27xx_codec.h index 5fdf0a0061..5a6796d63c 100644 --- a/firmware/export/rk27xx_codec.h +++ b/firmware/export/rk27xx_codec.h @@ -26,10 +26,14 @@ #define VOLUME_MIN -330 #define VOLUME_MAX 40 -#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP) +#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP | LIN_GAIN_CAP | MIC_GAIN_CAP) -extern int tenthdb2master(int db); -extern void audiohw_set_master_vol(int vol_l, int vol_r); +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -34, 4, -25) +#ifdef HAVE_RECORDING /* disabled for now */ +AUDIOHW_SETTING(LEFT_GAIN, "dB", 2, 75, -1725, 3000, 0) +AUDIOHW_SETTING(RIGHT_GAIN, "dB", 2, 75, -1725, 3000, 0) +AUDIOHW_SETTING(MIC_GAIN, "dB", 0, 1, 0, 20, 20) +#endif /* HAVE_RECORDING */ #define CODEC_I2C_ADDR 0x4e diff --git a/firmware/export/sound.h b/firmware/export/sound.h index ebf728c7c7..fa76c67b1f 100644 --- a/firmware/export/sound.h +++ b/firmware/export/sound.h @@ -24,17 +24,6 @@ #include #include - -#if CONFIG_CODEC == SWCODEC -enum { - DSP_CALLBACK_SET_PRESCALE = 0, - DSP_CALLBACK_SET_BASS, - DSP_CALLBACK_SET_TREBLE, - DSP_CALLBACK_SET_CHANNEL_CONFIG, - DSP_CALLBACK_SET_STEREO_WIDTH, -}; -#endif - typedef void sound_set_type(int value); const char *sound_unit(int setting); @@ -45,7 +34,6 @@ int sound_max(int setting); int sound_default(int setting); sound_set_type* sound_get_fn(int setting); -void sound_set_dsp_callback(int (*func)(int, intptr_t)); void sound_set_volume(int value); void sound_set_balance(int value); void sound_set_bass(int value); @@ -130,10 +118,8 @@ void sound_set_superbass(int value); void sound_set(int setting, int value); int sound_val2phys(int setting, int value); -#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) void sound_set_pitch(int32_t pitch); int32_t sound_get_pitch(void); -#endif #ifdef HAVE_PITCHCONTROL /* precision of the pitch and speed variables */ diff --git a/firmware/export/tlv320.h b/firmware/export/tlv320.h index 66f4d5ca92..99359f72ce 100644 --- a/firmware/export/tlv320.h +++ b/firmware/export/tlv320.h @@ -25,15 +25,33 @@ #define VOLUME_MIN -730 #define VOLUME_MAX 60 -extern int tenthdb2master(int db); +#define AUDIOHW_CAPS (LIN_GAIN_CAP | MIC_GAIN_CAP) + +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -74, 6, -20) +#ifdef HAVE_RECORDING + /* (x - 23)/1.5 *10 */ +AUDIOHW_SETTING(LEFT_GAIN, "dB", 1, 1, 0, 31, 23, (val - 23) * 15) +AUDIOHW_SETTING(RIGHT_GAIN, "dB", 1, 1, 0, 31, 23, (val - 23) * 15) +/* 0 or 20 dB */ +AUDIOHW_SETTING(MIC_GAIN, "dB", 1, 1, 0, 1, 1, val * 200) +#endif /* HAVE_RECORDING */ + +static inline int _param_2_phys(int setting, int value) +{ + switch(setting) + { + default: return value; +#ifdef HAVE_RECORDING + case SOUND_LEFT_GAIN: + case SOUND_RIGHT_GAIN: return (value - 23) * 15; + case SOUND_MIC_GAIN: return value * 200; /* 0 or 20 dB */ +#endif + } +} /*** definitions ***/ -extern void audiohw_set_headphone_vol(int vol_l, int vol_r); - #define HEADPHONE_MUTE 0x30 /* 0110000 = -73db */ -/* ToDo: samplerates */ - /* registers */ /* REG_LLIV: Left line input channel volume control */ #define REG_LLIV 0x0 diff --git a/firmware/export/tsc2100.h b/firmware/export/tsc2100.h index 9566c588df..4e1e7d9287 100644 --- a/firmware/export/tsc2100.h +++ b/firmware/export/tsc2100.h @@ -21,6 +21,12 @@ #ifndef __TSC2100_H_ #define __TSC2100_H_ +/* volume/balance/treble/bass interdependency */ +#define VOLUME_MIN -630 +#define VOLUME_MAX 0 + +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -64, 0, -25) + void tsc2100_read_data(void); bool tsc2100_read_touch(short *x, short* y, short *z1, short *z2); bool tsc2100_read_volt(short *bat1, short *bat2, short *aux); @@ -139,7 +145,4 @@ void tsc2100_keyclick(void); #define TSAC5_PAGE 2 #define TSAC5_ADDRESS 0x1e -extern int tenthdb2master(int db); -extern void audiohw_set_master_vol(int vol_l, int vol_r); - #endif diff --git a/firmware/export/uda1341.h b/firmware/export/uda1341.h index a43d33a137..5641bd301f 100644 --- a/firmware/export/uda1341.h +++ b/firmware/export/uda1341.h @@ -26,13 +26,16 @@ #define VOLUME_MIN -840 #define VOLUME_MAX 0 -#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP) +#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP | MIC_GAIN_CAP | LIN_GAIN_CAP) -extern int tenthdb2master(int db); -extern int tenthdb2mixer(int db); - -extern void audiohw_set_master_vol(int vol_l, int vol_r); -extern void audiohw_set_mixer_vol(int channel1, int channel2); +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -84, 0, -25) +AUDIOHW_SETTING(BASS, "dB", 0, 2, 0, 24, 0) +AUDIOHW_SETTING(TREBLE, "dB", 0, 2, 0, 6, 0) +#ifdef HAVE_RECORDING +AUDIOHW_SETTING(LEFT_GAIN, "dB", 1, 1,-128, 96, 0) +AUDIOHW_SETTING(RIGHT_GAIN, "dB", 1, 1,-128, 96, 0) +AUDIOHW_SETTING(MIC_GAIN, "dB", 1, 1,-128, 108, 16) +#endif /* HAVE_RECORDING */ /* These are logical register numbers for driver */ enum uda_register { diff --git a/firmware/export/uda1380.h b/firmware/export/uda1380.h index e9292cf466..a2200967dd 100644 --- a/firmware/export/uda1380.h +++ b/firmware/export/uda1380.h @@ -26,13 +26,18 @@ #define VOLUME_MIN -840 #define VOLUME_MAX 0 -#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP | PRESCALER_CAP) +#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP | PRESCALER_CAP | \ + LIN_GAIN_CAP | MIC_GAIN_CAP) -extern int tenthdb2master(int db); -extern int tenthdb2mixer(int db); - -extern void audiohw_set_master_vol(int vol_l, int vol_r); -extern void audiohw_set_mixer_vol(int channel1, int channel2); +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -85, 0, -25) +AUDIOHW_SETTING(BASS, "dB", 0, 2, 0, 24, 0) +AUDIOHW_SETTING(TREBLE, "dB", 0, 2, 0, 6, 0) +#ifdef HAVE_RECORDING + /* (1/2) * 10 */ +AUDIOHW_SETTING(LEFT_GAIN, "dB", 1, 1,-128, 96, 0, val * 5) +AUDIOHW_SETTING(RIGHT_GAIN, "dB", 1, 1,-128, 96, 0, val * 5) +AUDIOHW_SETTING(MIC_GAIN, "dB", 1, 1,-128, 108, 16, val * 5) +#endif /* HAVE_RECORDING */ #define UDA1380_ADDR 0x30 diff --git a/firmware/export/wm8731.h b/firmware/export/wm8731.h index 28d4d3940d..086c847ee1 100644 --- a/firmware/export/wm8731.h +++ b/firmware/export/wm8731.h @@ -28,9 +28,16 @@ #define VOLUME_MIN -730 #define VOLUME_MAX 60 -extern int tenthdb2master(int db); +#define AUDIOHW_CAPS (LIN_GAIN_CAP | MIC_GAIN_CAP) -extern void audiohw_set_master_vol(int vol_l, int vol_r); +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -74, 6, -25) +#if defined(HAVE_WM8731) && defined(HAVE_RECORDING) +/* (x - 23)/1.5 *10 */ +AUDIOHW_SETTING(LEFT_GAIN, "dB", 1, 1, 0, 31, 23, (val - 23) * 15) +AUDIOHW_SETTING(RIGHT_GAIN, "dB", 1, 1, 0, 31, 23, (val - 23) * 15) +/* 0 or 20 dB */ +AUDIOHW_SETTING(MIC_GAIN, "dB", 1, 1, 0, 1, 0, val * 200) +#endif /* defined(HAVE_WM8731) && defined(HAVE_RECORDING) */ /* Common register bits */ #ifdef HAVE_WM8731 diff --git a/firmware/export/wm8751.h b/firmware/export/wm8751.h index 3bbf744463..6e7bb245dd 100644 --- a/firmware/export/wm8751.h +++ b/firmware/export/wm8751.h @@ -25,23 +25,36 @@ #define VOLUME_MIN -730 #define VOLUME_MAX 60 -#if defined(HAVE_WM8750) #define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP | PRESCALER_CAP | \ BASS_CUTOFF_CAP | TREBLE_CUTOFF_CAP | \ - DEPTH_3D_CAP) -#else + DEPTH_3D_CAP | LIN_GAIN_CAP | MIC_GAIN_CAP) -#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP | PRESCALER_CAP | \ - BASS_CUTOFF_CAP | TREBLE_CUTOFF_CAP) -#endif +#if defined(HAVE_WM8750) +AUDIOHW_SETTING(DEPTH_3D, "%", 0, 1, 0, 15, 0, (100 * val + 8) / 15) +#ifdef HAVE_RECORDING + /* PGA -17.25dB to 30.0dB in 0.75dB increments 64 steps + * digital gain 0dB to 30.0dB in 0.5dB increments + * we use 0.75dB fake steps through whole range + * + * This combined gives -17.25 to 60.0dB + */ +AUDIOHW_SETTING(LEFT_GAIN, "dB", 2, 75,-1725, 6000, 0, val * 5) +AUDIOHW_SETTING(RIGHT_GAIN, "dB", 2, 75,-1725, 6000, 0, val * 5) +AUDIOHW_SETTING(MIC_GAIN, "dB", 2, 75,-1725, 6000, 3000, val * 5) -extern int tenthdb2master(int db); - -extern void audiohw_set_master_vol(int vol_l, int vol_r); -extern void audiohw_set_lineout_vol(int vol_l, int vol_r); -#if defined(HAVE_WM8750) && defined(HAVE_RECORDING) void audiohw_set_recsrc(int source, bool recording); -#endif +#endif /* HAVE_RECORDING */ +#else /* !HAVE_WM8750 */ +#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP | PRESCALER_CAP | \ + BASS_CUTOFF_CAP | TREBLE_CUTOFF_CAP | \ + LINEOUT_CAP) +#endif /* HAVE_WM8750 */ + +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -74, 6, -25) +AUDIOHW_SETTING(BASS, "dB", 1, 15, -60, 90, 0) +AUDIOHW_SETTING(TREBLE, "dB", 1, 15, -60, 90, 0) +AUDIOHW_SETTING(BASS_CUTOFF, "Hz", 0, 70, 130, 200, 200) +AUDIOHW_SETTING(TREBLE_CUTOFF, "kHz", 0, 4, 4, 8, 4) /* Register addresses and bits */ #define OUTPUT_MUTED 0x2f @@ -348,4 +361,5 @@ void audiohw_set_recsrc(int source, bool recording); #define MONOOUT_MOZC (1 << 7) #define WM_NUM_REGS 0x2b + #endif /* _WM8751_H */ diff --git a/firmware/export/wm8758.h b/firmware/export/wm8758.h index ef5567e898..89b000cf8c 100644 --- a/firmware/export/wm8758.h +++ b/firmware/export/wm8758.h @@ -26,15 +26,22 @@ #define VOLUME_MIN -890 #define VOLUME_MAX 60 -#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP | BASS_CUTOFF_CAP | TREBLE_CUTOFF_CAP) +#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP | BASS_CUTOFF_CAP | \ + TREBLE_CUTOFF_CAP | LINEOUT_CAP | LIN_GAIN_CAP | \ + MIC_GAIN_CAP) -extern int tenthdb2master(int db); -extern int tenthdb2mixer(int db); +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -90, 6, -25) +AUDIOHW_SETTING(BASS, "dB", 0, 1, -12, 12, 0) +AUDIOHW_SETTING(TREBLE, "dB", 0, 1, -12, 12, 0) +AUDIOHW_SETTING(BASS_CUTOFF, "", 0, 1, 1, 4, 1) +AUDIOHW_SETTING(TREBLE_CUTOFF, "", 0, 1, 1, 4, 1) +#ifdef HAVE_RECORDING +AUDIOHW_SETTING(LEFT_GAIN, "dB", 1, 1, 0, 63, 16, ((val - 23) * 15) / 2 + 200) +AUDIOHW_SETTING(RIGHT_GAIN, "dB", 1, 1, 0, 63, 16, ((val - 23) * 15) / 2 + 200) +AUDIOHW_SETTING(MIC_GAIN, "dB", 1, 1, 0, 63, 16, ((val - 23) * 15) / 2 + 200) +#endif /* HAVE_RECORDING */ -extern void audiohw_set_master_vol(int vol_l, int vol_r); -extern void audiohw_set_lineout_vol(int vol_l, int vol_r); -extern void audiohw_set_mixer_vol(int channel1, int channel2); -extern void audiohw_enable_lineout(bool enable); +void audiohw_enable_lineout(bool enable); #define RESET 0x00 #define RESET_RESET 0x0 diff --git a/firmware/export/wm8975.h b/firmware/export/wm8975.h index c9d0bd1bbe..f4e0d203a1 100644 --- a/firmware/export/wm8975.h +++ b/firmware/export/wm8975.h @@ -26,13 +26,19 @@ #define VOLUME_MIN -730 #define VOLUME_MAX 60 -#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP) +#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP | LINEOUT_CAP | \ + LIN_GAIN_CAP | MIC_GAIN_CAP) -extern int tenthdb2master(int db); +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -74, 6, -25) +AUDIOHW_SETTING(BASS, "dB", 0, 1, -6, 9, 0) +AUDIOHW_SETTING(TREBLE, "dB", 0, 1, -6, 9, 0) +#ifdef HAVE_RECORDING +AUDIOHW_SETTING(LEFT_GAIN, "dB", 1, 1, 0, 63, 23, ((val - 23) * 15) / 2) +AUDIOHW_SETTING(RIGHT_GAIN, "dB", 1, 1, 0, 63, 23, ((val - 23) * 15) / 2)) +AUDIOHW_SETTING(MIC_GAIN, "dB", 1, 1, 0, 63, 0, ((val - 23) * 15) / 2 + 200) +#endif /* HAVE_RECORDING */ -extern void audiohw_set_master_vol(int vol_l, int vol_r); -extern void audiohw_set_lineout_vol(int vol_l, int vol_r); -extern void audiohw_enable_lineout(bool enable); +void audiohw_enable_lineout(bool enable); /* Register addresses and bits */ diff --git a/firmware/export/wm8978.h b/firmware/export/wm8978.h index f591c1b9fb..d5ed8f184c 100644 --- a/firmware/export/wm8978.h +++ b/firmware/export/wm8978.h @@ -23,10 +23,17 @@ #ifndef _WM8978_H #define _WM8978_H -#define VOLUME_MIN -900 +#define VOLUME_MIN -890 #define VOLUME_MAX 60 -#define AUDIOHW_CAPS (EQ_CAP | PRESCALER_CAP | DEPTH_3D_CAP) +#if 0 +#define AUDIOHW_CAPS (EQ_CAP | PRESCALER_CAP | DEPTH_3D_CAP | \ + LIN_GAIN_CAP | MIC_GAIN_CAP) +#else +#define AUDIOHW_CAPS (EQ_CAP | PRESCALER_CAP | DEPTH_3D_CAP | \ + LIN_GAIN_CAP) +#endif + /* Filter bitmask */ #define AUDIOHW_EQ_BAND_CAPS ((EQ_CAP << 0) | (EQ_CAP << 1) | \ (EQ_CAP << 2) | (EQ_CAP << 3) | \ @@ -39,8 +46,33 @@ #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); +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -90, 6, -25) +AUDIOHW_SETTING(EQ_BAND1_GAIN, "dB", 0, 1, -12, 12, 0) +AUDIOHW_SETTING(EQ_BAND2_GAIN, "dB", 0, 1, -12, 12, 0) +AUDIOHW_SETTING(EQ_BAND3_GAIN, "dB", 0, 1, -12, 12, 0) +AUDIOHW_SETTING(EQ_BAND4_GAIN, "dB", 0, 1, -12, 12, 0) +AUDIOHW_SETTING(EQ_BAND5_GAIN, "dB", 0, 1, -12, 12, 0) +AUDIOHW_SETTING(EQ_BAND1_FREQUENCY, "", 0, 1, 0, 3, 0) +AUDIOHW_SETTING(EQ_BAND2_FREQUENCY, "", 0, 1, 0, 3, 0) +AUDIOHW_SETTING(EQ_BAND3_FREQUENCY, "", 0, 1, 0, 3, 0) +AUDIOHW_SETTING(EQ_BAND4_FREQUENCY, "", 0, 1, 0, 3, 0) +AUDIOHW_SETTING(EQ_BAND5_FREQUENCY, "", 0, 1, 0, 3, 0) +AUDIOHW_SETTING(EQ_BAND2_WIDTH, "", 0, 1, 0, 1, 0) +AUDIOHW_SETTING(EQ_BAND3_WIDTH, "", 0, 1, 0, 1, 0) +AUDIOHW_SETTING(EQ_BAND4_WIDTH, "", 0, 1, 0, 1, 0) +AUDIOHW_SETTING(DEPTH_3D, "%", 0, 1, 0, 15, 0, (100*val + 8) / 15) +#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. */ +AUDIOHW_SETTING(LEFT_GAIN, "dB", 1, 1,-238, 16, 0, val * 5) +AUDIOHW_SETTING(RIGHT_GAIN, "dB", 1, 1,-238, 16, 0, val * 5) +#if 0 /* whenever it's needed - none on GBS */ +AUDIOHW_SETTING(MIC_GAIN, "dB", 1, 1,-238, 16, 0, val * 5) +#endif /* 0 */ +#endif /* HAVE_RECORDING */ + void audiohw_set_recsrc(int source, bool recording); void wmc_set(unsigned int reg, unsigned int bits); diff --git a/firmware/export/wm8985.h b/firmware/export/wm8985.h index 4538b5edc5..a5eb59f159 100644 --- a/firmware/export/wm8985.h +++ b/firmware/export/wm8985.h @@ -29,15 +29,25 @@ #ifdef COWON_D2 /* FIXME: somehow something was out of sync in the .lang, settings and caps. Keep the * cutoffs disabled until someone with the device works it out. */ -#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP) +#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP | LINEOUT_CAP | \ + LIN_GAIN_CAP | MIC_GAIN_CAP) #else -#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP | BASS_CUTOFF_CAP | TREBLE_CUTOFF_CAP) +#define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP | BASS_CUTOFF_CAP | \ + TREBLE_CUTOFF_CAP | LINEOUT_CAP | LIN_GAIN_CAP | \ + MIC_GAIN_CAP) +AUDIOHW_SETTING(BASS_CUTOFF, "", 0, 1, 1, 4, 1) +AUDIOHW_SETTING(TREBLE_CUTOFF, "", 0, 1, 1, 4, 1) #endif -extern int tenthdb2master(int db); +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -90, 6, -25) +AUDIOHW_SETTING(BASS, "dB", 0, 1, -12, 12, 0) +AUDIOHW_SETTING(TREBLE, "dB", 0, 1, -12, 12, 0) +#ifdef HAVE_RECORDING +AUDIOHW_SETTING(LEFT_GAIN, "dB", 1, 1,-128, 96, 0) +AUDIOHW_SETTING(RIGHT_GAIN, "dB", 1, 1,-128, 96, 0) +AUDIOHW_SETTING(MIC_GAIN, "dB", 1, 1,-128, 108, 16) +#endif /* HAVE_RECORDING */ -extern void audiohw_set_headphone_vol(int vol_l, int vol_r); -extern void audiohw_set_lineout_vol(int vol_l, int vol_r); -extern void audiohw_set_aux_vol(int vol_l, int vol_r); +void audiohw_set_aux_vol(int vol_l, int vol_r); #endif /* _WM8985_H */ diff --git a/firmware/include/fixedpoint.h b/firmware/include/fixedpoint.h index 3e14bdd68e..584bd58d84 100644 --- a/firmware/include/fixedpoint.h +++ b/firmware/include/fixedpoint.h @@ -102,6 +102,11 @@ unsigned long isqrt(unsigned long x); #define FP_INF (0x7fffffff) #define FP_NEGINF -(0x7fffffff) +/** FIXED POINT EXP10 + * Return 10^x as FP integer. Argument is FP integer. + */ +long fp_exp10(long x, unsigned int fracbits); + /* fracbits in range 12 - 22 work well. Higher is better for * calculating dB, lower is better for calculating factor. */ diff --git a/firmware/sound.c b/firmware/sound.c index 7c86b0bf05..4c390f4a5b 100644 --- a/firmware/sound.c +++ b/firmware/sound.c @@ -9,6 +9,7 @@ * * Copyright (C) 2005 by Linus Nielsen Feltzing * Copyright (C) 2007 by Christian Gmeiner + * Copyright (C) 2013 by Michael Sevakis * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -19,141 +20,95 @@ * KIND, either express or implied. * ****************************************************************************/ -#include -#include + /* Indicate it's the sound.c file which affects compilation of audiohw.h */ +#define AUDIOHW_IS_SOUND_C #include "config.h" -#include "sound.h" -#include "logf.h" #include "system.h" -#include "i2c.h" +#include "sound.h" +#include "fixedpoint.h" #ifdef HAVE_SW_VOLUME_CONTROL #include "pcm_sw_volume.h" #endif /* HAVE_SW_VOLUME_CONTROL */ -/* TODO - * find a nice way to handle 1.5db steps -> see wm8751 ifdef in sound_set_bass/treble -*/ +/* Define sound_setting_entries table */ +#define AUDIOHW_SOUND_SETTINGS_ENTRIES +#include "audiohw_settings.h" + +/* Implements sound_val2phys */ +#define AUDIOHW_SOUND_SETTINGS_VAL2PHYS +#include "audiohw_settings.h" extern bool audio_is_initialized; -const char *sound_unit(int setting) +static const struct sound_setting_entry * get_setting_entry(int setting) { - return audiohw_settings[setting].unit; + static const struct sound_settings_info default_info = + { "", 0, 0, 0, 0, 0 }; + + static const struct sound_setting_entry default_entry = + { &default_info, NULL }; + + if ((unsigned)setting >= ARRAYLEN(sound_setting_entries)) + return &default_entry; + + const struct sound_setting_entry *e = &sound_setting_entries[setting]; + return e->info ? e : &default_entry; /* setting valid but not in table? */ +} + +static const struct sound_settings_info * get_settings_info(int setting) +{ + return get_setting_entry(setting)->info; +} + +const char * sound_unit(int setting) +{ + return get_settings_info(setting)->unit; } int sound_numdecimals(int setting) { - return audiohw_settings[setting].numdecimals; + return get_settings_info(setting)->numdecimals; } int sound_steps(int setting) { - return audiohw_settings[setting].steps; + return get_settings_info(setting)->steps; } int sound_min(int setting) { - return audiohw_settings[setting].minval; + return get_settings_info(setting)->minval; } int sound_max(int setting) { - return audiohw_settings[setting].maxval; + return get_settings_info(setting)->maxval; } int sound_default(int setting) { - return audiohw_settings[setting].defaultval; + return get_settings_info(setting)->defaultval; } -static sound_set_type * const sound_set_fns[] = +sound_set_type * sound_get_fn(int setting) { - [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, -#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) - [SOUND_LOUDNESS] = sound_set_loudness, - [SOUND_AVC] = sound_set_avc, - [SOUND_MDB_STRENGTH] = sound_set_mdb_strength, - [SOUND_MDB_HARMONICS] = sound_set_mdb_harmonics, - [SOUND_MDB_CENTER] = sound_set_mdb_center, - [SOUND_MDB_SHAPE] = sound_set_mdb_shape, - [SOUND_MDB_ENABLE] = sound_set_mdb_enable, - [SOUND_SUPERBASS] = sound_set_superbass, -#endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */ -#if defined(AUDIOHW_HAVE_BASS_CUTOFF) - [SOUND_BASS_CUTOFF] = sound_set_bass_cutoff, -#endif -#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) -{ - return ((unsigned)setting >= ARRAYLEN(sound_set_fns)? - NULL : sound_set_fns[setting]); + return get_setting_entry(setting)->function; } -#if CONFIG_CODEC == SWCODEC -static int (*dsp_callback)(int, intptr_t) = NULL; - -void sound_set_dsp_callback(int (*func)(int, intptr_t)) +void sound_set(int setting, int value) { - dsp_callback = func; + sound_set_type *sound_set_val = sound_get_fn(setting); + + if (sound_set_val) + sound_set_val(value); +} + +/* Return the sound value scaled to centibels (tenth-decibels) */ +static int sound_value_to_cb(int setting, int value) +{ + long e = (1 - sound_numdecimals(setting)) << 16; + return fp_mul(value, fp_exp10(e, 16), 16); } -#endif #if !defined(AUDIOHW_HAVE_CLIPPING) /* @@ -165,39 +120,31 @@ void sound_set_dsp_callback(int (*func)(int, intptr_t)) * by 12 dB after processing. */ -/* all values in tenth of dB MAS3507D UDA1380 */ -static int current_volume = 0; /* -780..+180 -840.. 0 */ -static int current_balance = 0; /* -960..+960 -840..+840 */ +static int current_volume = 0; /* tenth dB */ +static int current_balance = 0; /* percent */ #ifdef AUDIOHW_HAVE_TREBLE -static int current_treble = 0; /* -150..+150 0.. +60 */ +static int current_treble = 0; /* tenth dB */ #endif #ifdef AUDIOHW_HAVE_BASS -static int current_bass = 0; /* -150..+150 0..+240 */ +static int current_bass = 0; /* tenth dB */ #endif #ifdef AUDIOHW_HAVE_EQ -static int current_eq_band_gain[AUDIOHW_EQ_BAND_NUM]; +static int current_eq_band_gain[AUDIOHW_EQ_BAND_NUM]; /* tenth dB */ #endif static void set_prescaled_volume(void) { int prescale = 0; - int l, r; -/* The codecs listed use HW tone controls but don't have suitable prescaler - * functionality, so we let the prescaler stay at 0 for these, unless - * SW tone controls are in use. This is to avoid needing the SW DSP just for - * the prescaling. - */ -#if defined(HAVE_SW_TONE_CONTROLS) || !(defined(HAVE_WM8975) \ - || 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) \ + || defined(AUDIOHW_HAVE_EQ) + /* Note: Having Tone + EQ isn't prohibited */ #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++) + for (int i = 0; i < AUDIOHW_EQ_BAND_NUM; i++) prescale = MAX(current_eq_band_gain[i], prescale); #endif @@ -210,86 +157,65 @@ static void set_prescaled_volume(void) * instead (might cause clipping). */ if (current_volume + prescale > VOLUME_MAX) prescale = VOLUME_MAX - current_volume; -#endif -#if defined(AUDIOHW_HAVE_PRESCALER) audiohw_set_prescaler(prescale); -#else - dsp_callback(DSP_CALLBACK_SET_PRESCALE, prescale); -#endif - if (current_volume <= VOLUME_MIN) - prescale = 0; /* Make sure the chip gets muted at VOLUME_MIN */ + if (current_volume < VOLUME_MIN) + prescale = 0; /* Make sure the audio gets muted */ +#endif /* AUDIOHW_HAVE_BASS || AUDIOHW_HAVE_TREBLE || AUDIOHW_HAVE_EQ */ - l = r = current_volume + prescale; +#if defined(AUDIOHW_HAVE_MONO_VOLUME) + audiohw_set_volume(current_volume); +#else /* Stereo volume */ + int l = current_volume + prescale, r = l; /* Balance the channels scaled by the current volume and min volume. */ /* Subtract a dB from VOLUME_MIN to get it to a mute level */ - if (current_balance > 0) + int volshift = current_balance * VOLUME_RANGE / 100; /* tenth of dB */ + + if (volshift > 0) { - l -= ((l - (VOLUME_MIN - ONE_DB)) * current_balance) / VOLUME_RANGE; + l -= ((l - (VOLUME_MIN - ONE_DB)) * volshift) / VOLUME_RANGE; } - else if (current_balance < 0) + else if (volshift < 0) { - r += ((r - (VOLUME_MIN - ONE_DB)) * current_balance) / VOLUME_RANGE; + r += ((r - (VOLUME_MIN - ONE_DB)) * volshift) / VOLUME_RANGE; } -/* ypr0 with sdl has separate volume controls */ -#if defined(HAVE_SW_VOLUME_CONTROL) - audiohw_set_master_vol(l, r); -#elif !defined(HAVE_SDL_AUDIO) || defined(SAMSUNG_YPR0) -#if defined(HAVE_JZ4740_CODEC) - audiohw_set_master_vol(l, r); -#elif CONFIG_CODEC == MAS3507D - dac_volume(tenthdb2reg(l), tenthdb2reg(r), false); -#elif defined(HAVE_UDA1380) || defined(HAVE_WM8975) || defined(HAVE_WM8758) \ - || defined(HAVE_WM8711) || defined(HAVE_WM8721) || defined(HAVE_WM8731) \ - || defined(HAVE_WM8750) || defined(HAVE_WM8751) || defined(HAVE_AS3514) \ - || defined(HAVE_TSC2100) || defined(HAVE_AK4537) || defined(HAVE_UDA1341) \ - || defined(HAVE_CS42L55) || defined(HAVE_RK27XX_CODEC) - audiohw_set_master_vol(tenthdb2master(l), tenthdb2master(r)); -#if defined(HAVE_WM8975) || defined(HAVE_WM8758) \ - || (defined(HAVE_WM8751) && defined(TOSHIBA_GIGABEAT_F)) \ - || defined(HAVE_WM8985) || defined(HAVE_CS42L55) - audiohw_set_lineout_vol(tenthdb2master(0), tenthdb2master(0)); -#endif + audiohw_set_volume(l, r); +#endif /* AUDIOHW_HAVE_MONO_VOLUME */ -#elif defined(HAVE_TLV320) || defined(HAVE_WM8978) || defined(HAVE_WM8985) || defined(HAVE_IMX233_CODEC) || defined(HAVE_AIC3X) - audiohw_set_headphone_vol(tenthdb2master(l), tenthdb2master(r)); -#elif defined(HAVE_SDL_AUDIO) || defined(ANDROID) - audiohw_set_volume(current_volume); -#endif -#else /* HAVE_SDL_AUDIO */ - audiohw_set_volume(current_volume); -#endif /* !HAVE_SDL_AUDIO */ +#if defined(AUDIOHW_HAVE_LINEOUT) + /* For now, lineout stays at unity */ + audiohw_set_lineout_volume(0, 0); +#endif /* AUDIOHW_HAVE_LINEOUT */ + + (void)prescale; /* In case of no tone controls + mono volume */ } -#endif /* (CONFIG_CODEC == MAS3507D) || defined HAVE_UDA1380 */ +#endif /* AUDIOIHW_HAVE_CLIPPING */ void sound_set_volume(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; #if defined(AUDIOHW_HAVE_CLIPPING) audiohw_set_volume(value); -#elif CONFIG_CPU == PNX0101 - int tmp = (60 - value * 4) & 0xff; - CODECVOL = tmp | (tmp << 8); #else - current_volume = value * 10; /* tenth of dB */ + current_volume = sound_value_to_cb(SOUND_VOLUME, value); set_prescaled_volume(); #endif } void sound_set_balance(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; -#ifdef AUDIOHW_HAVE_BALANCE +#if defined(AUDIOHW_HAVE_BALANCE) audiohw_set_balance(value); #else - current_balance = value * VOLUME_RANGE / 100; /* tenth of dB */ + current_balance = value; set_prescaled_volume(); #endif } @@ -297,24 +223,13 @@ void sound_set_balance(int value) #ifdef AUDIOHW_HAVE_BASS void sound_set_bass(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; -#if !defined(AUDIOHW_HAVE_CLIPPING) -#if defined(HAVE_WM8750) || defined(HAVE_WM8751) || defined(HAVE_CS42L55) - current_bass = value; -#else - current_bass = value * 10; -#endif -#endif - -#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) + current_bass = sound_value_to_cb(SOUND_BASS, value); set_prescaled_volume(); #endif } @@ -323,24 +238,13 @@ void sound_set_bass(int value) #ifdef AUDIOHW_HAVE_TREBLE void sound_set_treble(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; -#if !defined(AUDIOHW_HAVE_CLIPPING) -#if defined(HAVE_WM8750) || defined(HAVE_WM8751) || defined(HAVE_CS42L55) - current_treble = value; -#else - current_treble = value * 10; -#endif -#endif - -#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) + current_treble = sound_value_to_cb(SOUND_TREBLE, value); set_prescaled_volume(); #endif } @@ -349,7 +253,7 @@ void sound_set_treble(int value) #if defined(AUDIOHW_HAVE_BASS_CUTOFF) void sound_set_bass_cutoff(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; audiohw_set_bass_cutoff(value); @@ -359,7 +263,7 @@ void sound_set_bass_cutoff(int value) #if defined(AUDIOHW_HAVE_TREBLE_CUTOFF) void sound_set_treble_cutoff(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; audiohw_set_treble_cutoff(value); @@ -368,32 +272,24 @@ void sound_set_treble_cutoff(int value) void sound_set_channels(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; -#if CONFIG_CODEC == SWCODEC - dsp_callback(DSP_CALLBACK_SET_CHANNEL_CONFIG, value); -#else audiohw_set_channel(value); -#endif } void sound_set_stereo_width(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; -#if CONFIG_CODEC == SWCODEC - dsp_callback(DSP_CALLBACK_SET_STEREO_WIDTH, value); -#else audiohw_set_stereo_width(value); -#endif } #if defined(AUDIOHW_HAVE_DEPTH_3D) void sound_set_depth_3d(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; audiohw_set_depth_3d(value); @@ -470,13 +366,11 @@ int sound_enum_hw_eq_band_setting(unsigned int band, static void sound_set_hw_eq_band_gain(unsigned int band, int value) { - int setting; - - if(!audio_is_initialized) + if (!audio_is_initialized) return; - setting = sound_enum_hw_eq_band_setting(band, AUDIOHW_EQ_GAIN); - current_eq_band_gain[band] = sound_val2phys(setting + 0x10000, value); + int setting = sound_enum_hw_eq_band_setting(band, AUDIOHW_EQ_GAIN); + current_eq_band_gain[band] = sound_value_to_cb(setting, value); audiohw_set_eq_band_gain(band, value); set_prescaled_volume(); @@ -518,7 +412,7 @@ void sound_set_hw_eq_band5_gain(int value) #if defined(AUDIOHW_HAVE_EQ_BAND1_FREQUENCY) void sound_set_hw_eq_band1_frequency(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; audiohw_set_eq_band_frequency(AUDIOHW_EQ_BAND1, value); @@ -528,7 +422,7 @@ void sound_set_hw_eq_band1_frequency(int value) #if defined(AUDIOHW_HAVE_EQ_BAND2_FREQUENCY) void sound_set_hw_eq_band2_frequency(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; audiohw_set_eq_band_frequency(AUDIOHW_EQ_BAND2, value); @@ -538,7 +432,7 @@ void sound_set_hw_eq_band2_frequency(int value) #if defined(AUDIOHW_HAVE_EQ_BAND3_FREQUENCY) void sound_set_hw_eq_band3_frequency(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; audiohw_set_eq_band_frequency(AUDIOHW_EQ_BAND3, value); @@ -548,7 +442,7 @@ void sound_set_hw_eq_band3_frequency(int value) #if defined(AUDIOHW_HAVE_EQ_BAND4_FREQUENCY) void sound_set_hw_eq_band4_frequency(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; audiohw_set_eq_band_frequency(AUDIOHW_EQ_BAND4, value); @@ -558,7 +452,7 @@ void sound_set_hw_eq_band4_frequency(int value) #if defined(AUDIOHW_HAVE_EQ_BAND5_FREQUENCY) void sound_set_hw_eq_band5_frequency(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; audiohw_set_eq_band_frequency(AUDIOHW_EQ_BAND5, value); @@ -568,7 +462,7 @@ void sound_set_hw_eq_band5_frequency(int value) #if defined(AUDIOHW_HAVE_EQ_BAND2_WIDTH) void sound_set_hw_eq_band2_width(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; audiohw_set_eq_band_width(AUDIOHW_EQ_BAND2, value); @@ -578,7 +472,7 @@ void sound_set_hw_eq_band2_width(int value) #if defined(AUDIOHW_HAVE_EQ_BAND3_WIDTH) void sound_set_hw_eq_band3_width(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; audiohw_set_eq_band_width(AUDIOHW_EQ_BAND3, value); @@ -588,7 +482,7 @@ void sound_set_hw_eq_band3_width(int value) #if defined(AUDIOHW_HAVE_EQ_BAND4_WIDTH) void sound_set_hw_eq_band4_width(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; audiohw_set_eq_band_width(AUDIOHW_EQ_BAND4, value); @@ -596,10 +490,10 @@ void sound_set_hw_eq_band4_width(int value) #endif #endif /* AUDIOHW_HAVE_EQ */ -#if ((CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)) +#if CONFIG_CODEC == MAS3587F || CONFIG_CODEC == MAS3539F void sound_set_loudness(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; audiohw_set_loudness(value); @@ -607,7 +501,7 @@ void sound_set_loudness(int value) void sound_set_avc(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; audiohw_set_avc(value); @@ -615,7 +509,7 @@ void sound_set_avc(int value) void sound_set_mdb_strength(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; audiohw_set_mdb_strength(value); @@ -623,7 +517,7 @@ void sound_set_mdb_strength(int value) void sound_set_mdb_harmonics(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; audiohw_set_mdb_harmonics(value); @@ -631,7 +525,7 @@ void sound_set_mdb_harmonics(int value) void sound_set_mdb_center(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; audiohw_set_mdb_center(value); @@ -639,7 +533,7 @@ void sound_set_mdb_center(int value) void sound_set_mdb_shape(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; audiohw_set_mdb_shape(value); @@ -647,7 +541,7 @@ void sound_set_mdb_shape(int value) void sound_set_mdb_enable(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; audiohw_set_mdb_enable(value); @@ -655,158 +549,27 @@ void sound_set_mdb_enable(int value) void sound_set_superbass(int value) { - if(!audio_is_initialized) + if (!audio_is_initialized) return; audiohw_set_superbass(value); } -#endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */ - -void sound_set(int setting, int value) -{ - sound_set_type* sound_set_val = sound_get_fn(setting); - if (sound_set_val) - sound_set_val(value); -} - -#if (!defined(HAVE_AS3514) && !defined(HAVE_WM8975) \ - && !defined(HAVE_WM8758) && !defined(HAVE_TSC2100) \ - && !defined (HAVE_WM8711) && !defined (HAVE_WM8721) \ - && !defined (HAVE_WM8731) && !defined (HAVE_WM8978) \ - && !defined (HAVE_WM8750) && !defined (HAVE_WM8751) \ - && !defined(HAVE_AK4537)) || defined(SIMULATOR) -int sound_val2phys(int setting, int value) -{ -#if CONFIG_CODEC == MAS3587F - int result = 0; - - switch(setting) - { - case SOUND_LEFT_GAIN: - case SOUND_RIGHT_GAIN: - result = (value - 2) * 15; - break; - - case SOUND_MIC_GAIN: - result = value * 15 + 210; - break; - - default: - result = value; - break; - } - return result; -#elif defined(HAVE_UDA1380) - int result = 0; - - switch(setting) - { -#ifdef HAVE_RECORDING - case SOUND_LEFT_GAIN: - case SOUND_RIGHT_GAIN: - case SOUND_MIC_GAIN: - result = value * 5; /* (1/2) * 10 */ - break; -#endif - default: - result = value; - break; - } - return result; -#elif defined(HAVE_TLV320) || defined(HAVE_WM8711) \ - || defined(HAVE_WM8721) || defined(HAVE_WM8731) - int result = 0; - - switch(setting) - { -#ifdef HAVE_RECORDING - case SOUND_LEFT_GAIN: - case SOUND_RIGHT_GAIN: - result = (value - 23) * 15; /* (x - 23)/1.5 *10 */ - break; - - case SOUND_MIC_GAIN: - result = value * 200; /* 0 or 20 dB */ - break; -#endif - default: - result = value; - break; - } - return result; -#elif defined(HAVE_AS3514) - /* This is here for the sim only and the audio driver has its own */ - int result; - - switch(setting) - { -#ifdef HAVE_RECORDING - case SOUND_LEFT_GAIN: - case SOUND_RIGHT_GAIN: - case SOUND_MIC_GAIN: - result = (value - 23) * 15; - break; -#endif - default: - result = value; - break; - } - - return result; -#elif defined(HAVE_WM8978) || defined(HAVE_WM8750) || defined(HAVE_WM8751) - int result; - - switch (setting) - { -#ifdef HAVE_RECORDING - case SOUND_LEFT_GAIN: - case SOUND_RIGHT_GAIN: - case SOUND_MIC_GAIN: - result = value * 5; - break; -#endif -#ifdef AUDIOHW_HAVE_DEPTH_3D - case SOUND_DEPTH_3D: - result = (100 * value + 8) / 15; - break; -#endif - default: - result = value; - } - - return result; -#else - (void)setting; - return value; -#endif -} -#endif /* CONFIG_CODECs || PLATFORM_HOSTED */ - -#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) -/* This function works by telling the decoder that we have another - crystal frequency than we actually have. It will adjust its internal - parameters and the result is that the audio is played at another pitch. -*/ - -static int last_pitch = PITCH_SPEED_100; +#endif /* CONFIG_CODEC == MAS3587F || CONFIG_CODEC == MAS3539F */ +#ifdef HAVE_PITCHCONTROL void sound_set_pitch(int32_t pitch) { - unsigned long val; + if (!audio_is_initialized) + return; - if (pitch != last_pitch) - { - /* Calculate the new (bogus) frequency */ - val = 18432 * PITCH_SPEED_100 / pitch; - - audiohw_set_pitch(val); - - last_pitch = pitch; - } + audiohw_set_pitch(pitch); } int32_t sound_get_pitch(void) { - return last_pitch; + if (!audio_is_initialized) + return PITCH_SPEED_100; + + return audiohw_get_pitch(); } -#endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */ +#endif /* HAVE_PITCHCONTROL */ diff --git a/firmware/target/arm/pnx0101/pcm-pnx0101.c b/firmware/target/arm/pnx0101/pcm-pnx0101.c index bb11ad32fe..a2394bc355 100644 --- a/firmware/target/arm/pnx0101/pcm-pnx0101.c +++ b/firmware/target/arm/pnx0101/pcm-pnx0101.c @@ -209,3 +209,9 @@ const void * pcm_play_dma_get_peak_buffer(int *count) *count = cnt >> 2; return (void *)((addr + 2) & ~3); } + +void audiohw_set_volume(int value) +{ + int tmp = (60 - value * 4) & 0xff; + CODECVOL = tmp | (tmp << 8); +} diff --git a/firmware/target/mips/ingenic_jz47xx/codec-jz4740.c b/firmware/target/mips/ingenic_jz47xx/codec-jz4740.c index 065433e12a..eae89cf78b 100644 --- a/firmware/target/mips/ingenic_jz47xx/codec-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/codec-jz4740.c @@ -26,30 +26,6 @@ #include "system.h" #include "pcm_sw_volume.h" -/* TODO */ -const struct sound_settings_info audiohw_settings[] = { -#ifdef HAVE_SW_VOLUME_CONTROL - [SOUND_VOLUME] = {"dB", 0, 1, -74, 6, -25}, -#else - [SOUND_VOLUME] = {"dB", 0, 1, 0, 6, 0}, -#endif - /* HAVE_SW_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}, -#ifdef HAVE_RECORDING - [SOUND_LEFT_GAIN] = {"dB", 1, 1, 0, 31, 23}, - [SOUND_RIGHT_GAIN] = {"dB", 1, 1, 0, 31, 23}, - [SOUND_MIC_GAIN] = {"dB", 1, 1, 0, 1, 1}, -#endif -}; - #if 0 static unsigned short codec_volume; static unsigned short codec_base_gain; diff --git a/lib/rbcodec/dsp/dsp_misc.c b/lib/rbcodec/dsp/dsp_misc.c index a8c9423cfb..672212b267 100644 --- a/lib/rbcodec/dsp/dsp_misc.c +++ b/lib/rbcodec/dsp/dsp_misc.c @@ -35,38 +35,6 @@ #endif #include -/** Firmware callback interface **/ - -/* Hook back from firmware/ part of audio, which can't/shouldn't call apps/ - * code directly. */ -int dsp_callback(int msg, intptr_t param) -{ - switch (msg) - { -#ifdef HAVE_SW_TONE_CONTROLS - case DSP_CALLBACK_SET_PRESCALE: - tone_set_prescale(param); - break; - case DSP_CALLBACK_SET_BASS: - tone_set_bass(param); - break; - case DSP_CALLBACK_SET_TREBLE: - tone_set_treble(param); - break; -#endif /* HAVE_SW_TONE_CONTROLS */ - case DSP_CALLBACK_SET_CHANNEL_CONFIG: - channel_mode_set_config(param); - break; - case DSP_CALLBACK_SET_STEREO_WIDTH: - channel_mode_custom_set_width(param); - break; - default: - break; - } - - return 0; -} - /** Replaygain settings **/ static struct replaygain_settings current_settings; static struct dsp_replay_gains current_gains; @@ -153,12 +121,7 @@ static void dsp_pitch_update(struct dsp_config *dsp) (int64_t)pitch_ratio * data->format.codec_frequency / PITCH_SPEED_100; } -int32_t sound_get_pitch(void) -{ - return pitch_ratio; -} - -void sound_set_pitch(int32_t percent) +static void dsp_set_pitch(int32_t percent) { pitch_ratio = percent > 0 ? percent : PITCH_SPEED_100; struct dsp_config *dsp = dsp_get_config(CODEC_IDX_AUDIO); @@ -167,6 +130,50 @@ void sound_set_pitch(int32_t percent) } #endif /* HAVE_PITCHCONTROL */ + +/** Firmware callback interface **/ + +/* Hook back from firmware/ part of audio, which can't/shouldn't call apps/ + * code directly. */ +int dsp_callback(int msg, intptr_t param) +{ + int retval = 0; + + switch (msg) + { +#ifdef HAVE_SW_TONE_CONTROLS + case DSP_CALLBACK_SET_PRESCALE: + tone_set_prescale(param); + break; + case DSP_CALLBACK_SET_BASS: + tone_set_bass(param); + break; + case DSP_CALLBACK_SET_TREBLE: + tone_set_treble(param); + break; +#endif /* HAVE_SW_TONE_CONTROLS */ + case DSP_CALLBACK_SET_CHANNEL_CONFIG: + channel_mode_set_config(param); + break; + case DSP_CALLBACK_SET_STEREO_WIDTH: + channel_mode_custom_set_width(param); + break; +#ifdef HAVE_PITCHCONTROL + case DSP_CALLBACK_SET_PITCH: + dsp_set_pitch(param); + break; + case DSP_CALLBACK_GET_PITCH: + retval = pitch_ratio; + break; +#endif /* HAVE_PITCHCONTROL */ + default: + break; + } + + return retval; +} + + /* This is a null-processing stage that monitors as an enabled stage but never * becomes active in processing samples. It only hooks messages. */ diff --git a/lib/rbcodec/dsp/dsp_misc.h b/lib/rbcodec/dsp/dsp_misc.h index d658374eaf..2583f495c3 100644 --- a/lib/rbcodec/dsp/dsp_misc.h +++ b/lib/rbcodec/dsp/dsp_misc.h @@ -54,12 +54,18 @@ struct dsp_replay_gains void dsp_replaygain_set_settings(const struct replaygain_settings *settings); -#ifdef HAVE_PITCHCONTROL -void sound_set_pitch(int32_t ratio); -int32_t sound_get_pitch(void); -#endif /* HAVE_PITCHCONTROL */ - /* Callback for firmware layers to interface */ +enum +{ + DSP_CALLBACK_SET_PRESCALE = 0, + DSP_CALLBACK_SET_BASS, + DSP_CALLBACK_SET_TREBLE, + DSP_CALLBACK_SET_CHANNEL_CONFIG, + DSP_CALLBACK_SET_STEREO_WIDTH, + DSP_CALLBACK_SET_PITCH, + DSP_CALLBACK_GET_PITCH, +}; + int dsp_callback(int msg, intptr_t param); #endif /* DSP_MISC_H */ diff --git a/lib/rbcodec/test/warble.c b/lib/rbcodec/test/warble.c index d5bc1c5aea..cd73a75542 100644 --- a/lib/rbcodec/test/warble.c +++ b/lib/rbcodec/test/warble.c @@ -354,7 +354,7 @@ static void perform_config(void) } else if (!strncmp(name, "offset=", 7)) { ci.id3->offset = atoi(val); } else if (!strncmp(name, "rate=", 5)) { - sound_set_pitch(atof(val) * PITCH_SPEED_100); + dsp_callback(DSP_CALLBACK_SET_PITCH, atof(val) * PITCH_SPEED_100); } else if (!strncmp(name, "seek=", 5)) { codec_action = CODEC_ACTION_SEEK_TIME; codec_action_param = atoi(val);