Gigabeat S: Turn off hardware effects (tone and 3d) when doing digital loopback for FM recording otherwise the signal and levels are poorly represented in monitoring (can't just do ADC->DAC for general FM and get voice too). Some tweaking to input setup to improve gain a tiny bit. A little bit quieter startup too.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26300 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Michael Sevakis 2010-05-26 05:13:45 +00:00
parent ab27aa1526
commit 72ccb14ab1
2 changed files with 87 additions and 33 deletions

View file

@ -129,13 +129,17 @@ static uint16_t wmc_regs[WMC_NUM_REGISTERS] =
struct struct
{ {
int vol_l; signed char vol_l;
int vol_r; signed char vol_r;
int dac_l; unsigned char dac_l;
int dac_r; unsigned char dac_r;
bool ahw_mute; unsigned char ahw_mute;
int prescaler; unsigned char prescaler; /* Attenuation */
int enhance_3d_prescaler; unsigned char eq_on; /* Enabled */
signed char band_gain[5]; /* Setting */
unsigned char enh_3d_prescaler; /* Attenuation */
unsigned char enh_3d_on; /* Enabled */
unsigned char enh_3d; /* Setting */
} wmc_vol = } wmc_vol =
{ {
.vol_l = 0, .vol_l = 0,
@ -144,7 +148,11 @@ struct
.dac_r = 0, .dac_r = 0,
.ahw_mute = false, .ahw_mute = false,
.prescaler = 0, .prescaler = 0,
.enhance_3d_prescaler = 0, .eq_on = true,
.band_gain = { 0, 0, 0, 0, 0 },
.enh_3d_prescaler = 0,
.enh_3d_on = true,
.enh_3d = 0,
}; };
static void wmc_write(unsigned int reg, unsigned int val) static void wmc_write(unsigned int reg, unsigned int val)
@ -252,14 +260,14 @@ void audiohw_preinit(void)
/* 5. Set BIASEN = 1 in register R1. */ /* 5. Set BIASEN = 1 in register R1. */
wmc_set(WMC_POWER_MANAGEMENT1, WMC_BIASEN); wmc_set(WMC_POWER_MANAGEMENT1, WMC_BIASEN);
/* 6. Set L/ROUTEN = 1 in register R2. */
wmc_write(WMC_POWER_MANAGEMENT2, WMC_LOUT1EN | WMC_ROUT1EN);
} }
void audiohw_postinit(void) void audiohw_postinit(void)
{ {
sleep(HZ); sleep(5*HZ/4);
/* 6. Set L/ROUTEN = 1 in register R2. */
wmc_write(WMC_POWER_MANAGEMENT2, WMC_LOUT1EN | WMC_ROUT1EN);
/* 7. Enable other mixers as required */ /* 7. Enable other mixers as required */
@ -316,6 +324,23 @@ static void get_headphone_levels(int val, int *dac_p, int *hp_p,
*boost_p = boost; *boost_p = boost;
} }
static void sync_prescaler(void)
{
int prescaler = 0;
/* Combine all prescaling into a single DAC attenuation */
if (wmc_vol.eq_on)
prescaler = wmc_vol.prescaler * 2;
if (wmc_vol.enh_3d_on)
prescaler += wmc_vol.enh_3d_prescaler;
wmc_write_masked(WMC_LEFT_DAC_DIGITAL_VOL, wmc_vol.dac_l - prescaler,
WMC_DVOL);
wmc_write_masked(WMC_RIGHT_DAC_DIGITAL_VOL, wmc_vol.dac_r - prescaler,
WMC_DVOL);
}
void audiohw_set_headphone_vol(int vol_l, int vol_r) void audiohw_set_headphone_vol(int vol_l, int vol_r)
{ {
int prev_l = wmc_vol.vol_l; int prev_l = wmc_vol.vol_l;
@ -334,21 +359,18 @@ void audiohw_set_headphone_vol(int vol_l, int vol_r)
wmc_vol.dac_l = dac_l; wmc_vol.dac_l = dac_l;
wmc_vol.dac_r = dac_r; wmc_vol.dac_r = dac_r;
dac_l -= wmc_vol.prescaler + wmc_vol.enhance_3d_prescaler; sync_prescaler();
dac_r -= wmc_vol.prescaler + wmc_vol.enhance_3d_prescaler;
wmc_write_masked(WMC_LEFT_MIXER_CTRL, mix_l << WMC_BYPLMIXVOL_POS, wmc_write_masked(WMC_LEFT_MIXER_CTRL, mix_l << WMC_BYPLMIXVOL_POS,
WMC_BYPLMIXVOL); WMC_BYPLMIXVOL);
wmc_write_masked(WMC_LEFT_ADC_BOOST_CTRL, wmc_write_masked(WMC_LEFT_ADC_BOOST_CTRL,
boost_l << WMC_L2_2BOOSTVOL_POS, WMC_L2_2BOOSTVOL); boost_l << WMC_L2_2BOOSTVOL_POS, WMC_L2_2BOOSTVOL);
wmc_write_masked(WMC_LEFT_DAC_DIGITAL_VOL, dac_l, WMC_DVOL);
wmc_write_masked(WMC_LOUT1_HP_VOLUME_CTRL, hp_l, WMC_AVOL); wmc_write_masked(WMC_LOUT1_HP_VOLUME_CTRL, hp_l, WMC_AVOL);
wmc_write_masked(WMC_RIGHT_MIXER_CTRL, mix_r << WMC_BYPRMIXVOL_POS, wmc_write_masked(WMC_RIGHT_MIXER_CTRL, mix_r << WMC_BYPRMIXVOL_POS,
WMC_BYPRMIXVOL); WMC_BYPRMIXVOL);
wmc_write_masked(WMC_RIGHT_ADC_BOOST_CTRL, wmc_write_masked(WMC_RIGHT_ADC_BOOST_CTRL,
boost_r << WMC_R2_2BOOSTVOL_POS, WMC_R2_2BOOSTVOL); boost_r << WMC_R2_2BOOSTVOL_POS, WMC_R2_2BOOSTVOL);
wmc_write_masked(WMC_RIGHT_DAC_DIGITAL_VOL, dac_r, WMC_DVOL);
wmc_write_masked(WMC_ROUT1_HP_VOLUME_CTRL, hp_r, WMC_AVOL); wmc_write_masked(WMC_ROUT1_HP_VOLUME_CTRL, hp_r, WMC_AVOL);
if (vol_l > 0) if (vol_l > 0)
@ -405,6 +427,11 @@ void audiohw_set_eq_band_gain(unsigned int band, int val)
if (band > 4) if (band > 4)
return; return;
wmc_vol.band_gain[band] = val;
if (!wmc_vol.eq_on)
val = 0;
wmc_write_masked(band + WMC_EQ1_LOW_SHELF, 12 - val, WMC_EQG); wmc_write_masked(band + WMC_EQ1_LOW_SHELF, 12 - val, WMC_EQG);
} }
@ -433,27 +460,20 @@ void audiohw_set_eq_band_width(unsigned int band, int val)
* gain to EQ bands. */ * gain to EQ bands. */
void audiohw_set_prescaler(int val) void audiohw_set_prescaler(int val)
{ {
val *= 2;
wmc_vol.prescaler = val; wmc_vol.prescaler = val;
val += wmc_vol.enhance_3d_prescaler; /* Combine with 3D attenuation */ sync_prescaler();
wmc_write_masked(WMC_LEFT_DAC_DIGITAL_VOL, wmc_vol.dac_l - val,
WMC_DVOL);
wmc_write_masked(WMC_RIGHT_DAC_DIGITAL_VOL, wmc_vol.dac_r - val,
WMC_DVOL);
} }
/* Set the depth of the 3D effect */ /* Set the depth of the 3D effect */
void audiohw_set_depth_3d(int val) void audiohw_set_depth_3d(int val)
{ {
int att = 10*val / 15; /* -5 dB @ full setting */ wmc_vol.enh_3d_prescaler = 10*val / 15; /* -5 dB @ full setting */
wmc_vol.enhance_3d_prescaler = att; wmc_vol.enh_3d = val;
att += wmc_vol.prescaler; /* Combine with prescaler attenuation */
wmc_write_masked(WMC_LEFT_DAC_DIGITAL_VOL, wmc_vol.dac_l - att, if (!wmc_vol.enh_3d_on)
WMC_DVOL); val = 0;
wmc_write_masked(WMC_RIGHT_DAC_DIGITAL_VOL, wmc_vol.dac_r - att,
WMC_DVOL); sync_prescaler();
wmc_write_masked(WMC_3D_CONTROL, val, WMC_DEPTH3D); wmc_write_masked(WMC_3D_CONTROL, val, WMC_DEPTH3D);
} }
@ -599,6 +619,22 @@ void audiohw_set_frequency(int fsel)
} }
} }
void audiohw_enable_tone_controls(bool enable)
{
int i;
wmc_vol.eq_on = enable;
audiohw_set_prescaler(wmc_vol.prescaler);
for (i = 0; i < 5; i++)
audiohw_set_eq_band_gain(i, wmc_vol.band_gain[i]);
}
void audiohw_enable_depth_3d(bool enable)
{
wmc_vol.enh_3d_on = enable;
audiohw_set_depth_3d(wmc_vol.enh_3d);
}
#ifdef HAVE_RECORDING #ifdef HAVE_RECORDING
void audiohw_set_recsrc(int source, bool recording) void audiohw_set_recsrc(int source, bool recording)
{ {
@ -615,7 +651,9 @@ void audiohw_set_recsrc(int source, bool recording)
/* Disable IP BOOSTMIX and PGA */ /* Disable IP BOOSTMIX and PGA */
wmc_clear(WMC_POWER_MANAGEMENT2, WMC_INPPGAENL | WMC_INPPGAENR | wmc_clear(WMC_POWER_MANAGEMENT2, WMC_INPPGAENL | WMC_INPPGAENR |
WMC_BOOSTENL | WMC_BOOSTENR); WMC_BOOSTENL | WMC_BOOSTENR);
wmc_clear(WMC_INPUT_CTRL, WMC_L2_2INPPGA | WMC_R2_2INPPGA); wmc_clear(WMC_INPUT_CTRL, WMC_L2_2INPPGA | WMC_R2_2INPPGA |
WMC_LIP2INPPGA | WMC_RIP2INPPGA |
WMC_LIN2INPPGA | WMC_RIN2INPPGA);
wmc_clear(WMC_LEFT_ADC_BOOST_CTRL, WMC_PGABOOSTL); wmc_clear(WMC_LEFT_ADC_BOOST_CTRL, WMC_PGABOOSTL);
wmc_clear(WMC_RIGHT_ADC_BOOST_CTRL, WMC_PGABOOSTR); wmc_clear(WMC_RIGHT_ADC_BOOST_CTRL, WMC_PGABOOSTR);
break; break;
@ -637,7 +675,11 @@ void audiohw_set_recsrc(int source, bool recording)
wmc_set(WMC_LEFT_ADC_BOOST_CTRL, WMC_PGABOOSTL); wmc_set(WMC_LEFT_ADC_BOOST_CTRL, WMC_PGABOOSTL);
wmc_set(WMC_RIGHT_ADC_BOOST_CTRL, WMC_PGABOOSTR); wmc_set(WMC_RIGHT_ADC_BOOST_CTRL, WMC_PGABOOSTR);
/* Connect L/R2 inputs to PGA */ /* Connect L/R2 inputs to PGA */
wmc_set(WMC_INPUT_CTRL, WMC_L2_2INPPGA | WMC_R2_2INPPGA); wmc_write_masked(WMC_INPUT_CTRL, WMC_L2_2INPPGA | WMC_R2_2INPPGA |
WMC_LIN2INPPGA | WMC_RIN2INPPGA,
WMC_L2_2INPPGA | WMC_R2_2INPPGA |
WMC_LIP2INPPGA | WMC_RIP2INPPGA |
WMC_LIN2INPPGA | WMC_RIN2INPPGA);
} }
else else
{ {
@ -647,7 +689,9 @@ void audiohw_set_recsrc(int source, bool recording)
wmc_write_masked(WMC_POWER_MANAGEMENT2, WMC_BOOSTENL | WMC_BOOSTENR, wmc_write_masked(WMC_POWER_MANAGEMENT2, WMC_BOOSTENL | WMC_BOOSTENR,
WMC_BOOSTENL | WMC_BOOSTENR | WMC_INPPGAENL | WMC_BOOSTENL | WMC_BOOSTENR | WMC_INPPGAENL |
WMC_INPPGAENR | WMC_ADCENL | WMC_ADCENR); WMC_INPPGAENR | WMC_ADCENL | WMC_ADCENR);
wmc_clear(WMC_INPUT_CTRL, WMC_L2_2INPPGA | WMC_R2_2INPPGA); wmc_clear(WMC_INPUT_CTRL, WMC_L2_2INPPGA | WMC_R2_2INPPGA |
WMC_LIP2INPPGA | WMC_RIP2INPPGA |
WMC_LIN2INPPGA | WMC_RIN2INPPGA);
wmc_clear(WMC_LEFT_ADC_BOOST_CTRL, WMC_PGABOOSTL); wmc_clear(WMC_LEFT_ADC_BOOST_CTRL, WMC_PGABOOSTL);
wmc_clear(WMC_RIGHT_ADC_BOOST_CTRL, WMC_PGABOOSTR); wmc_clear(WMC_RIGHT_ADC_BOOST_CTRL, WMC_PGABOOSTR);
/* Enable bypass to L/R mixers */ /* Enable bypass to L/R mixers */

View file

@ -23,6 +23,9 @@
#include "audiohw.h" #include "audiohw.h"
#include "audio.h" #include "audio.h"
void audiohw_enable_tone_controls(bool enable);
void audiohw_enable_depth_3d(bool enable);
/* Set the audio source for IIS TX */ /* Set the audio source for IIS TX */
void audio_set_output_source(int source) void audio_set_output_source(int source)
{ {
@ -30,12 +33,19 @@ void audio_set_output_source(int source)
{ {
default: default:
case AUDIO_SRC_PLAYBACK: case AUDIO_SRC_PLAYBACK:
audiohw_enable_tone_controls(true);
audiohw_enable_depth_3d(true);
/* Receive data from PORT2 (SSI2) */ /* Receive data from PORT2 (SSI2) */
AUDMUX_PDCR4 = AUDMUX_PDCR_RXDSEL_PORT2; AUDMUX_PDCR4 = AUDMUX_PDCR_RXDSEL_PORT2;
/* wmc_clear(WMC_COMPANDING_CTRL, WMC_LOOPBACK); */ /* wmc_clear(WMC_COMPANDING_CTRL, WMC_LOOPBACK); */
break; break;
case AUDIO_SRC_FMRADIO: case AUDIO_SRC_FMRADIO:
/* Analog path doesn't support these and digital radio playback
* cannot be done without mixing on the MCU if voice is to be
* heard. Any recording should match what is heard. */
audiohw_enable_tone_controls(false);
audiohw_enable_depth_3d(false);
/* External source - receive data from self (loopback to TX) */ /* External source - receive data from self (loopback to TX) */
AUDMUX_PDCR4 = AUDMUX_PDCR_RXDSEL_PORT4; AUDMUX_PDCR4 = AUDMUX_PDCR_RXDSEL_PORT4;
/* wmc_set(WMC_COMPANDING_CTRL, WMC_LOOPBACK); */ /* wmc_set(WMC_COMPANDING_CTRL, WMC_LOOPBACK); */