From 3c7c79189e2912ac179deab21c92ffb3448b128b Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Sat, 1 Aug 2009 21:38:18 +0000 Subject: [PATCH] * Move DSP_CALLBACK_* enum to sound.h * Add software based volume control for a certain range (SW_VOLUME_MIN -> SW_VOLUME_MAX) * Make Onda VX747 use it * Don't change volume or frequency in Ingenic Jz4740 codec driver when they're already set git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22106 a1c6a512-1295-4272-9138-f99709370657 --- apps/dsp.c | 14 ++++++++++ apps/dsp.h | 8 ------ firmware/export/config-ondavx747.h | 8 ++++++ firmware/export/sound.h | 13 +++++++++ firmware/sound.c | 14 +++------- .../target/mips/ingenic_jz47xx/codec-jz4740.c | 27 +++++++++---------- 6 files changed, 52 insertions(+), 32 deletions(-) diff --git a/apps/dsp.c b/apps/dsp.c index ec59417621..f9b94e8228 100644 --- a/apps/dsp.c +++ b/apps/dsp.c @@ -890,6 +890,15 @@ static void set_gain(struct dsp_config *dsp) (long) (((int64_t) dsp->data.gain * eq_precut) >> 24); } +#ifdef HAVE_SW_VOLUME_CONTROL + if (global_settings.volume < SW_VOLUME_MAX || + global_settings.volume > SW_VOLUME_MIN) + { + int vol_gain = get_replaygain_int(global_settings.volume * 100); + dsp->data.gain = (long) (((int64_t) dsp->data.gain * vol_gain) >> 24); + } +#endif + if (dsp->data.gain == DEFAULT_GAIN) { dsp->data.gain = 0; @@ -1149,6 +1158,11 @@ int dsp_callback(int msg, intptr_t param) case DSP_CALLBACK_SET_TREBLE: treble = param; break; +#ifdef HAVE_SW_VOLUME_CONTROL + case DSP_CALLBACK_SET_SW_VOLUME: + set_gain(&AUDIO_DSP); + break; +#endif #endif case DSP_CALLBACK_SET_CHANNEL_CONFIG: dsp_set_channel_config(param); diff --git a/apps/dsp.h b/apps/dsp.h index 7d1e2b3ddc..58a5edb5e2 100644 --- a/apps/dsp.h +++ b/apps/dsp.h @@ -56,14 +56,6 @@ enum DSP_CROSSFEED }; -enum { - DSP_CALLBACK_SET_PRESCALE = 0, - DSP_CALLBACK_SET_BASS, - DSP_CALLBACK_SET_TREBLE, - DSP_CALLBACK_SET_CHANNEL_CONFIG, - DSP_CALLBACK_SET_STEREO_WIDTH -}; - struct dsp_config; int dsp_process(struct dsp_config *dsp, char *dest, diff --git a/firmware/export/config-ondavx747.h b/firmware/export/config-ondavx747.h index ffcaf67c5a..a04b55f1e3 100644 --- a/firmware/export/config-ondavx747.h +++ b/firmware/export/config-ondavx747.h @@ -139,6 +139,14 @@ /* has no tone controls, so we use the software ones */ #define HAVE_SW_TONE_CONTROLS +/* has no volume control, so we use the software ones */ +#define HAVE_SW_VOLUME_CONTROL + +/* software controlled volume ranges from -73 -> 0 dB, other than that + is controlled by hardware */ +#define SW_VOLUME_MIN -73 +#define SW_VOLUME_MAX 0 + /* define the bitmask of hardware sample rates */ #define HW_SAMPR_CAPS (SAMPR_CAP_48 | SAMPR_CAP_44 | SAMPR_CAP_32 | \ SAMPR_CAP_24 | SAMPR_CAP_22 | SAMPR_CAP_16 | \ diff --git a/firmware/export/sound.h b/firmware/export/sound.h index 3d12a47db3..2e13174516 100644 --- a/firmware/export/sound.h +++ b/firmware/export/sound.h @@ -24,6 +24,19 @@ #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, +#ifdef HAVE_SW_VOLUME_CONTROL + DSP_CALLBACK_SET_SW_VOLUME, +#endif +}; +#endif + typedef void sound_set_type(int value); const char *sound_unit(int setting); diff --git a/firmware/sound.c b/firmware/sound.c index 84ccd2b1bd..b327e3839c 100644 --- a/firmware/sound.c +++ b/firmware/sound.c @@ -158,16 +158,6 @@ sound_set_type* sound_get_fn(int setting) } #if CONFIG_CODEC == SWCODEC -/* Copied from dsp.h, nasty nasty, but we don't want to include dsp.h */ - -enum { - DSP_CALLBACK_SET_PRESCALE = 0, - DSP_CALLBACK_SET_BASS, - DSP_CALLBACK_SET_TREBLE, - DSP_CALLBACK_SET_CHANNEL_CONFIG, - DSP_CALLBACK_SET_STEREO_WIDTH -}; - static int (*dsp_callback)(int, intptr_t) = NULL; void sound_set_dsp_callback(int (*func)(int, intptr_t)) @@ -251,6 +241,10 @@ static void set_prescaled_volume(void) r += ((r - (VOLUME_MIN - ONE_DB)) * current_balance) / VOLUME_RANGE; } +#ifdef HAVE_SW_VOLUME_CONTROL + dsp_callback(DSP_CALLBACK_SET_SW_VOLUME, 0); +#endif + #if CONFIG_CODEC == MAS3507D dac_volume(tenthdb2reg(l), tenthdb2reg(r), false); #elif defined(HAVE_UDA1380) || defined(HAVE_WM8975) || defined(HAVE_WM8758) \ diff --git a/firmware/target/mips/ingenic_jz47xx/codec-jz4740.c b/firmware/target/mips/ingenic_jz47xx/codec-jz4740.c index b91b7fae70..3a124e1356 100644 --- a/firmware/target/mips/ingenic_jz47xx/codec-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/codec-jz4740.c @@ -27,7 +27,8 @@ /* TODO */ const struct sound_settings_info audiohw_settings[] = { - [SOUND_VOLUME] = {"dB", 0, 2, 0, 6, 0}, + /* HAVE_SW_VOLUME_CONTROL */ + [SOUND_VOLUME] = {"dB", 0, 1, SW_VOLUME_MIN, 6, 0}, /* HAVE_SW_TONE_CONTROLS */ [SOUND_BASS] = {"dB", 0, 1, -24, 24, 0}, [SOUND_TREBLE] = {"dB", 0, 1, -24, 24, 0}, @@ -79,7 +80,7 @@ static void i2s_codec_init(void) REG_ICDC_CDCCR1 &= ~(ICDC_CDCCR1_SUSPD | ICDC_CDCCR1_RST); - REG_ICDC_CDCCR2 = ( ICDC_CDCCR2_AINVOL(14) | ICDC_CDCCR2_SMPR(ICDC_CDCCR2_SMPR_44) + REG_ICDC_CDCCR2 = ( ICDC_CDCCR2_AINVOL(23) | ICDC_CDCCR2_SMPR(ICDC_CDCCR2_SMPR_44) | ICDC_CDCCR2_HPVOL(ICDC_CDCCR2_HPVOL_0)); mdelay(15); @@ -287,9 +288,14 @@ void audiohw_init(void) void audiohw_set_volume(int v) { - /* 0 <= v <= 60 */ - unsigned int codec_volume = v / 20; - REG_ICDC_CDCCR2 = (REG_ICDC_CDCCR2 & ~ICDC_CDCCR2_HPVOL(0x3)) | ICDC_CDCCR2_HPVOL(codec_volume); + if(v >= 0) + { + /* 0 <= v <= 60 */ + unsigned int codec_volume = ICDC_CDCCR2_HPVOL(v / 20); + + if((REG_ICDC_CDCCR2 & ICDC_CDCCR2_HPVOL(0x3)) != codec_volume) + REG_ICDC_CDCCR2 = (REG_ICDC_CDCCR2 & ~ICDC_CDCCR2_HPVOL(0x3)) | codec_volume; + } } void audiohw_set_frequency(int freq) @@ -329,7 +335,8 @@ void audiohw_set_frequency(int freq) return; } - REG_ICDC_CDCCR2 = (REG_ICDC_CDCCR2 & ~ICDC_CDCCR2_SMPR(0xF)) | speed; + if((REG_ICDC_CDCCR2 & ICDC_CDCCR2_SMPR(0xF)) != speed) + REG_ICDC_CDCCR2 = (REG_ICDC_CDCCR2 & ~ICDC_CDCCR2_SMPR(0xF)) | speed; } int audio_channels = 2; @@ -356,20 +363,16 @@ void audio_input_mux(int source, unsigned flags) case AUDIO_SRC_PLAYBACK: audio_channels = 2; if(source != last_source) - { REG_ICDC_CDCCR1 = (REG_ICDC_CDCCR1 & ~(ICDC_CDCCR1_ELININ | ICDC_CDCCR1_EMIC | ICDC_CDCCR1_EADC | ICDC_CDCCR1_SW1ON | ICDC_CDCCR1_HPMUTE)) | (ICDC_CDCCR1_EDAC | ICDC_CDCCR1_SW2ON); - } break; #if INPUT_SRC_CAPS & SRC_CAP_MIC case AUDIO_SRC_MIC: /* recording only */ audio_channels = 1; if(source != last_source) - { REG_ICDC_CDCCR1 = (REG_ICDC_CDCCR1 & ~(ICDC_CDCCR1_ELININ | ICDC_CDCCR1_EDAC | ICDC_CDCCR1_SW2ON | ICDC_CDCCR1_HPMUTE)) | (ICDC_CDCCR1_EADC | ICDC_CDCCR1_SW1ON | ICDC_CDCCR1_EMIC); - } break; #endif @@ -383,15 +386,11 @@ void audio_input_mux(int source, unsigned flags) last_recording = recording; if(recording) - { REG_ICDC_CDCCR1 = (REG_ICDC_CDCCR1 & ~(ICDC_CDCCR1_EMIC | ICDC_CDCCR1_EDAC | ICDC_CDCCR1_SW2ON | ICDC_CDCCR1_HPMUTE)) | (ICDC_CDCCR1_EADC | ICDC_CDCCR1_SW1ON | ICDC_CDCCR1_ELININ); - } else - { REG_ICDC_CDCCR1 = (REG_ICDC_CDCCR1 & ~(ICDC_CDCCR1_EMIC | ICDC_CDCCR1_EDAC | ICDC_CDCCR1_EADC | ICDC_CDCCR1_SW2ON | ICDC_CDCCR1_HPMUTE)) | (ICDC_CDCCR1_SW1ON | ICDC_CDCCR1_ELININ); - } break; #endif } /* end switch */