summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2010-05-26 05:13:45 +0000
committerMichael Sevakis <jethead71@rockbox.org>2010-05-26 05:13:45 +0000
commit72ccb14ab1a2b38b89120330378ecec64fc8df7b (patch)
tree41b364e3a53772b6663fcf34a31c755a85c8c702
parentab27aa1526983cf1992ce8974c61a3b10ac551dd (diff)
downloadrockbox-72ccb14ab1a2b38b89120330378ecec64fc8df7b.tar.gz
rockbox-72ccb14ab1a2b38b89120330378ecec64fc8df7b.zip
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
-rw-r--r--firmware/drivers/audio/wm8978.c110
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/audio-gigabeat-s.c10
2 files changed, 87 insertions, 33 deletions
diff --git a/firmware/drivers/audio/wm8978.c b/firmware/drivers/audio/wm8978.c
index 2d57ce3f10..2a19e22df3 100644
--- a/firmware/drivers/audio/wm8978.c
+++ b/firmware/drivers/audio/wm8978.c
@@ -129,13 +129,17 @@ static uint16_t wmc_regs[WMC_NUM_REGISTERS] =
129 129
130struct 130struct
131{ 131{
132 int vol_l; 132 signed char vol_l;
133 int vol_r; 133 signed char vol_r;
134 int dac_l; 134 unsigned char dac_l;
135 int dac_r; 135 unsigned char dac_r;
136 bool ahw_mute; 136 unsigned char ahw_mute;
137 int prescaler; 137 unsigned char prescaler; /* Attenuation */
138 int enhance_3d_prescaler; 138 unsigned char eq_on; /* Enabled */
139 signed char band_gain[5]; /* Setting */
140 unsigned char enh_3d_prescaler; /* Attenuation */
141 unsigned char enh_3d_on; /* Enabled */
142 unsigned char enh_3d; /* Setting */
139} wmc_vol = 143} wmc_vol =
140{ 144{
141 .vol_l = 0, 145 .vol_l = 0,
@@ -144,7 +148,11 @@ struct
144 .dac_r = 0, 148 .dac_r = 0,
145 .ahw_mute = false, 149 .ahw_mute = false,
146 .prescaler = 0, 150 .prescaler = 0,
147 .enhance_3d_prescaler = 0, 151 .eq_on = true,
152 .band_gain = { 0, 0, 0, 0, 0 },
153 .enh_3d_prescaler = 0,
154 .enh_3d_on = true,
155 .enh_3d = 0,
148}; 156};
149 157
150static void wmc_write(unsigned int reg, unsigned int val) 158static void wmc_write(unsigned int reg, unsigned int val)
@@ -252,14 +260,14 @@ void audiohw_preinit(void)
252 260
253 /* 5. Set BIASEN = 1 in register R1. */ 261 /* 5. Set BIASEN = 1 in register R1. */
254 wmc_set(WMC_POWER_MANAGEMENT1, WMC_BIASEN); 262 wmc_set(WMC_POWER_MANAGEMENT1, WMC_BIASEN);
263
264 /* 6. Set L/ROUTEN = 1 in register R2. */
265 wmc_write(WMC_POWER_MANAGEMENT2, WMC_LOUT1EN | WMC_ROUT1EN);
255} 266}
256 267
257void audiohw_postinit(void) 268void audiohw_postinit(void)
258{ 269{
259 sleep(HZ); 270 sleep(5*HZ/4);
260
261 /* 6. Set L/ROUTEN = 1 in register R2. */
262 wmc_write(WMC_POWER_MANAGEMENT2, WMC_LOUT1EN | WMC_ROUT1EN);
263 271
264 /* 7. Enable other mixers as required */ 272 /* 7. Enable other mixers as required */
265 273
@@ -316,6 +324,23 @@ static void get_headphone_levels(int val, int *dac_p, int *hp_p,
316 *boost_p = boost; 324 *boost_p = boost;
317} 325}
318 326
327static void sync_prescaler(void)
328{
329 int prescaler = 0;
330
331 /* Combine all prescaling into a single DAC attenuation */
332 if (wmc_vol.eq_on)
333 prescaler = wmc_vol.prescaler * 2;
334
335 if (wmc_vol.enh_3d_on)
336 prescaler += wmc_vol.enh_3d_prescaler;
337
338 wmc_write_masked(WMC_LEFT_DAC_DIGITAL_VOL, wmc_vol.dac_l - prescaler,
339 WMC_DVOL);
340 wmc_write_masked(WMC_RIGHT_DAC_DIGITAL_VOL, wmc_vol.dac_r - prescaler,
341 WMC_DVOL);
342}
343
319void audiohw_set_headphone_vol(int vol_l, int vol_r) 344void audiohw_set_headphone_vol(int vol_l, int vol_r)
320{ 345{
321 int prev_l = wmc_vol.vol_l; 346 int prev_l = wmc_vol.vol_l;
@@ -334,21 +359,18 @@ void audiohw_set_headphone_vol(int vol_l, int vol_r)
334 wmc_vol.dac_l = dac_l; 359 wmc_vol.dac_l = dac_l;
335 wmc_vol.dac_r = dac_r; 360 wmc_vol.dac_r = dac_r;
336 361
337 dac_l -= wmc_vol.prescaler + wmc_vol.enhance_3d_prescaler; 362 sync_prescaler();
338 dac_r -= wmc_vol.prescaler + wmc_vol.enhance_3d_prescaler;
339 363
340 wmc_write_masked(WMC_LEFT_MIXER_CTRL, mix_l << WMC_BYPLMIXVOL_POS, 364 wmc_write_masked(WMC_LEFT_MIXER_CTRL, mix_l << WMC_BYPLMIXVOL_POS,
341 WMC_BYPLMIXVOL); 365 WMC_BYPLMIXVOL);
342 wmc_write_masked(WMC_LEFT_ADC_BOOST_CTRL, 366 wmc_write_masked(WMC_LEFT_ADC_BOOST_CTRL,
343 boost_l << WMC_L2_2BOOSTVOL_POS, WMC_L2_2BOOSTVOL); 367 boost_l << WMC_L2_2BOOSTVOL_POS, WMC_L2_2BOOSTVOL);
344 wmc_write_masked(WMC_LEFT_DAC_DIGITAL_VOL, dac_l, WMC_DVOL);
345 wmc_write_masked(WMC_LOUT1_HP_VOLUME_CTRL, hp_l, WMC_AVOL); 368 wmc_write_masked(WMC_LOUT1_HP_VOLUME_CTRL, hp_l, WMC_AVOL);
346 369
347 wmc_write_masked(WMC_RIGHT_MIXER_CTRL, mix_r << WMC_BYPRMIXVOL_POS, 370 wmc_write_masked(WMC_RIGHT_MIXER_CTRL, mix_r << WMC_BYPRMIXVOL_POS,
348 WMC_BYPRMIXVOL); 371 WMC_BYPRMIXVOL);
349 wmc_write_masked(WMC_RIGHT_ADC_BOOST_CTRL, 372 wmc_write_masked(WMC_RIGHT_ADC_BOOST_CTRL,
350 boost_r << WMC_R2_2BOOSTVOL_POS, WMC_R2_2BOOSTVOL); 373 boost_r << WMC_R2_2BOOSTVOL_POS, WMC_R2_2BOOSTVOL);
351 wmc_write_masked(WMC_RIGHT_DAC_DIGITAL_VOL, dac_r, WMC_DVOL);
352 wmc_write_masked(WMC_ROUT1_HP_VOLUME_CTRL, hp_r, WMC_AVOL); 374 wmc_write_masked(WMC_ROUT1_HP_VOLUME_CTRL, hp_r, WMC_AVOL);
353 375
354 if (vol_l > 0) 376 if (vol_l > 0)
@@ -405,6 +427,11 @@ void audiohw_set_eq_band_gain(unsigned int band, int val)
405 if (band > 4) 427 if (band > 4)
406 return; 428 return;
407 429
430 wmc_vol.band_gain[band] = val;
431
432 if (!wmc_vol.eq_on)
433 val = 0;
434
408 wmc_write_masked(band + WMC_EQ1_LOW_SHELF, 12 - val, WMC_EQG); 435 wmc_write_masked(band + WMC_EQ1_LOW_SHELF, 12 - val, WMC_EQG);
409} 436}
410 437
@@ -433,27 +460,20 @@ void audiohw_set_eq_band_width(unsigned int band, int val)
433 * gain to EQ bands. */ 460 * gain to EQ bands. */
434void audiohw_set_prescaler(int val) 461void audiohw_set_prescaler(int val)
435{ 462{
436 val *= 2;
437 wmc_vol.prescaler = val; 463 wmc_vol.prescaler = val;
438 val += wmc_vol.enhance_3d_prescaler; /* Combine with 3D attenuation */ 464 sync_prescaler();
439
440 wmc_write_masked(WMC_LEFT_DAC_DIGITAL_VOL, wmc_vol.dac_l - val,
441 WMC_DVOL);
442 wmc_write_masked(WMC_RIGHT_DAC_DIGITAL_VOL, wmc_vol.dac_r - val,
443 WMC_DVOL);
444} 465}
445 466
446/* Set the depth of the 3D effect */ 467/* Set the depth of the 3D effect */
447void audiohw_set_depth_3d(int val) 468void audiohw_set_depth_3d(int val)
448{ 469{
449 int att = 10*val / 15; /* -5 dB @ full setting */ 470 wmc_vol.enh_3d_prescaler = 10*val / 15; /* -5 dB @ full setting */
450 wmc_vol.enhance_3d_prescaler = att; 471 wmc_vol.enh_3d = val;
451 att += wmc_vol.prescaler; /* Combine with prescaler attenuation */
452 472
453 wmc_write_masked(WMC_LEFT_DAC_DIGITAL_VOL, wmc_vol.dac_l - att, 473 if (!wmc_vol.enh_3d_on)
454 WMC_DVOL); 474 val = 0;
455 wmc_write_masked(WMC_RIGHT_DAC_DIGITAL_VOL, wmc_vol.dac_r - att, 475
456 WMC_DVOL); 476 sync_prescaler();
457 wmc_write_masked(WMC_3D_CONTROL, val, WMC_DEPTH3D); 477 wmc_write_masked(WMC_3D_CONTROL, val, WMC_DEPTH3D);
458} 478}
459 479
@@ -599,6 +619,22 @@ void audiohw_set_frequency(int fsel)
599 } 619 }
600} 620}
601 621
622void audiohw_enable_tone_controls(bool enable)
623{
624 int i;
625 wmc_vol.eq_on = enable;
626 audiohw_set_prescaler(wmc_vol.prescaler);
627
628 for (i = 0; i < 5; i++)
629 audiohw_set_eq_band_gain(i, wmc_vol.band_gain[i]);
630}
631
632void audiohw_enable_depth_3d(bool enable)
633{
634 wmc_vol.enh_3d_on = enable;
635 audiohw_set_depth_3d(wmc_vol.enh_3d);
636}
637
602#ifdef HAVE_RECORDING 638#ifdef HAVE_RECORDING
603void audiohw_set_recsrc(int source, bool recording) 639void audiohw_set_recsrc(int source, bool recording)
604{ 640{
@@ -615,7 +651,9 @@ void audiohw_set_recsrc(int source, bool recording)
615 /* Disable IP BOOSTMIX and PGA */ 651 /* Disable IP BOOSTMIX and PGA */
616 wmc_clear(WMC_POWER_MANAGEMENT2, WMC_INPPGAENL | WMC_INPPGAENR | 652 wmc_clear(WMC_POWER_MANAGEMENT2, WMC_INPPGAENL | WMC_INPPGAENR |
617 WMC_BOOSTENL | WMC_BOOSTENR); 653 WMC_BOOSTENL | WMC_BOOSTENR);
618 wmc_clear(WMC_INPUT_CTRL, WMC_L2_2INPPGA | WMC_R2_2INPPGA); 654 wmc_clear(WMC_INPUT_CTRL, WMC_L2_2INPPGA | WMC_R2_2INPPGA |
655 WMC_LIP2INPPGA | WMC_RIP2INPPGA |
656 WMC_LIN2INPPGA | WMC_RIN2INPPGA);
619 wmc_clear(WMC_LEFT_ADC_BOOST_CTRL, WMC_PGABOOSTL); 657 wmc_clear(WMC_LEFT_ADC_BOOST_CTRL, WMC_PGABOOSTL);
620 wmc_clear(WMC_RIGHT_ADC_BOOST_CTRL, WMC_PGABOOSTR); 658 wmc_clear(WMC_RIGHT_ADC_BOOST_CTRL, WMC_PGABOOSTR);
621 break; 659 break;
@@ -637,7 +675,11 @@ void audiohw_set_recsrc(int source, bool recording)
637 wmc_set(WMC_LEFT_ADC_BOOST_CTRL, WMC_PGABOOSTL); 675 wmc_set(WMC_LEFT_ADC_BOOST_CTRL, WMC_PGABOOSTL);
638 wmc_set(WMC_RIGHT_ADC_BOOST_CTRL, WMC_PGABOOSTR); 676 wmc_set(WMC_RIGHT_ADC_BOOST_CTRL, WMC_PGABOOSTR);
639 /* Connect L/R2 inputs to PGA */ 677 /* Connect L/R2 inputs to PGA */
640 wmc_set(WMC_INPUT_CTRL, WMC_L2_2INPPGA | WMC_R2_2INPPGA); 678 wmc_write_masked(WMC_INPUT_CTRL, WMC_L2_2INPPGA | WMC_R2_2INPPGA |
679 WMC_LIN2INPPGA | WMC_RIN2INPPGA,
680 WMC_L2_2INPPGA | WMC_R2_2INPPGA |
681 WMC_LIP2INPPGA | WMC_RIP2INPPGA |
682 WMC_LIN2INPPGA | WMC_RIN2INPPGA);
641 } 683 }
642 else 684 else
643 { 685 {
@@ -647,7 +689,9 @@ void audiohw_set_recsrc(int source, bool recording)
647 wmc_write_masked(WMC_POWER_MANAGEMENT2, WMC_BOOSTENL | WMC_BOOSTENR, 689 wmc_write_masked(WMC_POWER_MANAGEMENT2, WMC_BOOSTENL | WMC_BOOSTENR,
648 WMC_BOOSTENL | WMC_BOOSTENR | WMC_INPPGAENL | 690 WMC_BOOSTENL | WMC_BOOSTENR | WMC_INPPGAENL |
649 WMC_INPPGAENR | WMC_ADCENL | WMC_ADCENR); 691 WMC_INPPGAENR | WMC_ADCENL | WMC_ADCENR);
650 wmc_clear(WMC_INPUT_CTRL, WMC_L2_2INPPGA | WMC_R2_2INPPGA); 692 wmc_clear(WMC_INPUT_CTRL, WMC_L2_2INPPGA | WMC_R2_2INPPGA |
693 WMC_LIP2INPPGA | WMC_RIP2INPPGA |
694 WMC_LIN2INPPGA | WMC_RIN2INPPGA);
651 wmc_clear(WMC_LEFT_ADC_BOOST_CTRL, WMC_PGABOOSTL); 695 wmc_clear(WMC_LEFT_ADC_BOOST_CTRL, WMC_PGABOOSTL);
652 wmc_clear(WMC_RIGHT_ADC_BOOST_CTRL, WMC_PGABOOSTR); 696 wmc_clear(WMC_RIGHT_ADC_BOOST_CTRL, WMC_PGABOOSTR);
653 /* Enable bypass to L/R mixers */ 697 /* Enable bypass to L/R mixers */
diff --git a/firmware/target/arm/imx31/gigabeat-s/audio-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/audio-gigabeat-s.c
index f5e17a4039..9587b5683c 100644
--- a/firmware/target/arm/imx31/gigabeat-s/audio-gigabeat-s.c
+++ b/firmware/target/arm/imx31/gigabeat-s/audio-gigabeat-s.c
@@ -23,6 +23,9 @@
23#include "audiohw.h" 23#include "audiohw.h"
24#include "audio.h" 24#include "audio.h"
25 25
26void audiohw_enable_tone_controls(bool enable);
27void audiohw_enable_depth_3d(bool enable);
28
26/* Set the audio source for IIS TX */ 29/* Set the audio source for IIS TX */
27void audio_set_output_source(int source) 30void audio_set_output_source(int source)
28{ 31{
@@ -30,12 +33,19 @@ void audio_set_output_source(int source)
30 { 33 {
31 default: 34 default:
32 case AUDIO_SRC_PLAYBACK: 35 case AUDIO_SRC_PLAYBACK:
36 audiohw_enable_tone_controls(true);
37 audiohw_enable_depth_3d(true);
33 /* Receive data from PORT2 (SSI2) */ 38 /* Receive data from PORT2 (SSI2) */
34 AUDMUX_PDCR4 = AUDMUX_PDCR_RXDSEL_PORT2; 39 AUDMUX_PDCR4 = AUDMUX_PDCR_RXDSEL_PORT2;
35 /* wmc_clear(WMC_COMPANDING_CTRL, WMC_LOOPBACK); */ 40 /* wmc_clear(WMC_COMPANDING_CTRL, WMC_LOOPBACK); */
36 break; 41 break;
37 42
38 case AUDIO_SRC_FMRADIO: 43 case AUDIO_SRC_FMRADIO:
44 /* Analog path doesn't support these and digital radio playback
45 * cannot be done without mixing on the MCU if voice is to be
46 * heard. Any recording should match what is heard. */
47 audiohw_enable_tone_controls(false);
48 audiohw_enable_depth_3d(false);
39 /* External source - receive data from self (loopback to TX) */ 49 /* External source - receive data from self (loopback to TX) */
40 AUDMUX_PDCR4 = AUDMUX_PDCR_RXDSEL_PORT4; 50 AUDMUX_PDCR4 = AUDMUX_PDCR_RXDSEL_PORT4;
41 /* wmc_set(WMC_COMPANDING_CTRL, WMC_LOOPBACK); */ 51 /* wmc_set(WMC_COMPANDING_CTRL, WMC_LOOPBACK); */