From 8867d001419158b0a4112661583c59f49632be81 Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Mon, 5 Mar 2007 08:14:27 +0000 Subject: [PATCH] More catching up on old work. Refine audio interface setup on Coldfire. Stop the funky glitching on the iAudio stuff when starting recording esp. at 88.2kHz. (probably due to the bidi interface). iRivers don't seem to care what you do. TLV320 still seems to have a little trouble selecting it's filters correctly for 88.2kHz or it could be some odd phasing effect. Get rid of the horrible reset parameter in pcm_apply_settings as it can decide for itself. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12618 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugin.h | 2 +- firmware/export/pcm_playback.h | 2 +- firmware/pcm_record.c | 6 +- .../target/arm/gigabeat/meg-fx/pcm-meg-fx.c | 3 +- firmware/target/coldfire/iaudio/m5/audio-m5.c | 7 +- firmware/target/coldfire/iaudio/x5/audio-x5.c | 12 +- .../target/coldfire/iriver/audio-iriver.c | 22 +-- firmware/target/coldfire/pcm-coldfire.c | 162 ++++++++++-------- firmware/target/coldfire/system-coldfire.c | 5 + firmware/target/coldfire/system-target.h | 3 + 10 files changed, 123 insertions(+), 101 deletions(-) diff --git a/apps/plugin.h b/apps/plugin.h index 5135006bdb..62ede9bce8 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -568,7 +568,7 @@ struct plugin_api { const unsigned long *audio_master_sampr_list; const unsigned long *hw_freq_sampr; #ifndef SIMULATOR - void (*pcm_apply_settings)(bool reset); + void (*pcm_apply_settings)(void); #endif #ifdef HAVE_RECORDING const unsigned long *rec_freq_sampr; diff --git a/firmware/export/pcm_playback.h b/firmware/export/pcm_playback.h index 80a1f557fe..28409c01d9 100644 --- a/firmware/export/pcm_playback.h +++ b/firmware/export/pcm_playback.h @@ -33,7 +33,7 @@ void pcm_init(void); */ void pcm_set_frequency(unsigned int frequency); /* apply settings to hardware immediately */ -void pcm_apply_settings(bool reset); +void pcm_apply_settings(void); /* This is for playing "raw" PCM data */ void pcm_play_data(pcm_more_callback_type get_more, diff --git a/firmware/pcm_record.c b/firmware/pcm_record.c index 3f4abc7be3..f467b734c8 100644 --- a/firmware/pcm_record.c +++ b/firmware/pcm_record.c @@ -329,7 +329,7 @@ static void reset_hardware(void) /* reset pcm to defaults (playback only) */ pcm_set_frequency(HW_SAMPR_DEFAULT); audio_set_output_source(AUDIO_SRC_PLAYBACK); - pcm_apply_settings(true); + pcm_apply_settings(); } /** pcm_rec_* group **/ @@ -1326,8 +1326,8 @@ static void pcmrec_set_recording_options( /* set monitoring */ audio_set_output_source(rec_source); - /* apply pcm settings to hardware */ - pcm_apply_settings(true); + /* apply hardware setting to start monitoring now */ + pcm_apply_settings(); queue_reply(&pcmrec_queue, 0); /* Release sender */ diff --git a/firmware/target/arm/gigabeat/meg-fx/pcm-meg-fx.c b/firmware/target/arm/gigabeat/meg-fx/pcm-meg-fx.c index fcfe813ab7..7e1cebc555 100644 --- a/firmware/target/arm/gigabeat/meg-fx/pcm-meg-fx.c +++ b/firmware/target/arm/gigabeat/meg-fx/pcm-meg-fx.c @@ -282,9 +282,8 @@ size_t pcm_get_bytes_waiting(void) /* dummy functions for those not actually supporting all this yet */ -void pcm_apply_settings(bool reset) +void pcm_apply_settings(void) { - (void)reset; } void pcm_set_monitor(int monitor) diff --git a/firmware/target/coldfire/iaudio/m5/audio-m5.c b/firmware/target/coldfire/iaudio/m5/audio-m5.c index fcedbcad78..9531f932ad 100644 --- a/firmware/target/coldfire/iaudio/m5/audio-m5.c +++ b/firmware/target/coldfire/iaudio/m5/audio-m5.c @@ -49,8 +49,7 @@ void audio_set_source(int source, unsigned flags) { audiohw_disable_recording(); audiohw_set_monitor(false); - /* Reset PDIR2 data flow */ - DATAINCONTROL = (1 << 9); + coldfire_set_dataincontrol(0); } break; @@ -59,7 +58,7 @@ void audio_set_source(int source, unsigned flags) { audiohw_enable_recording(true); /* source mic */ /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */ - DATAINCONTROL = (3 << 14) | (4 << 3); + coldfire_set_dataincontrol((3 << 14) | (4 << 3)); } break; @@ -68,7 +67,7 @@ void audio_set_source(int source, unsigned flags) { audiohw_enable_recording(false); /* source line */ /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */ - DATAINCONTROL = (3 << 14) | (4 << 3); + coldfire_set_dataincontrol((3 << 14) | (4 << 3)); } break; } /* end switch */ diff --git a/firmware/target/coldfire/iaudio/x5/audio-x5.c b/firmware/target/coldfire/iaudio/x5/audio-x5.c index 23aaa42cd6..e673d4ad47 100644 --- a/firmware/target/coldfire/iaudio/x5/audio-x5.c +++ b/firmware/target/coldfire/iaudio/x5/audio-x5.c @@ -50,8 +50,7 @@ void audio_set_source(int source, unsigned flags) { audiohw_disable_recording(); audiohw_set_monitor(false); - /* Reset PDIR2 data flow */ - DATAINCONTROL = (1 << 9); + coldfire_set_dataincontrol(0); } break; @@ -60,7 +59,7 @@ void audio_set_source(int source, unsigned flags) { audiohw_enable_recording(true); /* source mic */ /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */ - DATAINCONTROL = (3 << 14) | (4 << 3); + coldfire_set_dataincontrol((3 << 14) | (4 << 3)); } break; @@ -69,7 +68,7 @@ void audio_set_source(int source, unsigned flags) { audiohw_enable_recording(false); /* source line */ /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */ - DATAINCONTROL = (3 << 14) | (4 << 3); + coldfire_set_dataincontrol((3 << 14) | (4 << 3)); } break; @@ -86,15 +85,14 @@ void audio_set_source(int source, unsigned flags) if (recording) { /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */ - DATAINCONTROL = (3 << 14) | (4 << 3); + coldfire_set_dataincontrol((3 << 14) | (4 << 3)); audiohw_enable_recording(false); /* source line */ } else { audiohw_disable_recording(); audiohw_set_monitor(true); /* analog bypass */ - /* Reset PDIR2 data flow */ - DATAINCONTROL = (1 << 9); + coldfire_set_dataincontrol(0); } break; } /* end switch */ diff --git a/firmware/target/coldfire/iriver/audio-iriver.c b/firmware/target/coldfire/iriver/audio-iriver.c index 751025d08a..2df7a216a9 100644 --- a/firmware/target/coldfire/iriver/audio-iriver.c +++ b/firmware/target/coldfire/iriver/audio-iriver.c @@ -56,8 +56,7 @@ void audio_set_source(int source, unsigned flags) { audiohw_disable_recording(); audiohw_set_monitor(false); - /* Reset PDIR2 data flow */ - DATAINCONTROL = (1 << 9); + coldfire_set_dataincontrol(0); } break; @@ -67,7 +66,7 @@ void audio_set_source(int source, unsigned flags) audiohw_enable_recording(true); /* source mic */ audiohw_set_monitor(false); /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */ - DATAINCONTROL = (3 << 14) | (4 << 3); + coldfire_set_dataincontrol((3 << 14) | (4 << 3)); } break; @@ -77,7 +76,7 @@ void audio_set_source(int source, unsigned flags) audiohw_enable_recording(false); /* source line */ audiohw_set_monitor(false); /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */ - DATAINCONTROL = (3 << 14) | (4 << 3); + coldfire_set_dataincontrol((3 << 14) | (4 << 3)); } break; @@ -88,7 +87,7 @@ void audio_set_source(int source, unsigned flags) audiohw_disable_recording(); audiohw_set_monitor(false); /* Int. when 6 samples in FIFO, PDIR2 src = ebu1RcvData */ - DATAINCONTROL = (3 << 14) | (7 << 3); + coldfire_set_dataincontrol((3 << 14) | (7 << 3)); } break; #endif /* HAVE_SPDIF_IN */ @@ -102,16 +101,9 @@ void audio_set_source(int source, unsigned flags) last_recording = recording; - if (recording) - { - /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */ - DATAINCONTROL = (3 << 14) | (4 << 3); - } - else - { - /* Reset PDIR2 data flow */ - DATAINCONTROL = (1 << 9); - } + /* Int. when 6 samples in FIFO, PDIR2 src = iis1RcvData */ + coldfire_set_dataincontrol(recording ? + ((3 << 14) | (4 << 3)) : 0); /* I2S recording and playback */ audiohw_enable_recording(false); /* source line */ diff --git a/firmware/target/coldfire/pcm-coldfire.c b/firmware/target/coldfire/pcm-coldfire.c index 8738316aa9..2addcb9da8 100644 --- a/firmware/target/coldfire/pcm-coldfire.c +++ b/firmware/target/coldfire/pcm-coldfire.c @@ -41,22 +41,22 @@ enum }; static int peaks[4]; /* p-l, p-r, r-l, r-r */ -#define IIS_DEFPARM(output) ( (freq_ent[FPARM_CLOCKSEL] << 12) | \ - (output) | \ - (4 << 2) ) /* 64 bit clocks / word clock */ -#define IIS_RESET 0x800 +#define IIS_PLAY_DEFPARM ( (freq_ent[FPARM_CLOCKSEL] << 12) | \ + (IIS_PLAY & (7 << 8)) | \ + (4 << 2) ) /* 64 bit clocks / word clock */ +#define IIS_FIFO_RESET (1 << 11) +#define PDIR2_FIFO_RESET (1 << 9) #if defined(IAUDIO_X5) || defined(IAUDIO_M5) -#define SET_IIS_CONFIG(x) IIS1CONFIG = (x); -#define IIS_CONFIG IIS1CONFIG +#define SET_IIS_PLAY(x) IIS1CONFIG = (x) +#define IIS_PLAY IIS1CONFIG +#else +#define SET_IIS_PLAY(x) IIS2CONFIG = (x) +#define IIS_PLAY IIS2CONFIG +#endif + #define PLLCR_SET_AUDIO_BITS_DEFPARM \ ((freq_ent[FPARM_CLSEL] << 28) | (1 << 22)) -#else -#define SET_IIS_CONFIG(x) IIS2CONFIG = (x); -#define IIS_CONFIG IIS2CONFIG -#define PLLCR_SET_AUDIO_BITS_DEFPARM \ - ((freq_ent[FPARM_CLSEL] << 28) | (3 << 22)) -#endif /** Sample rates **/ #define FPARM_CLOCKSEL 0 @@ -113,29 +113,31 @@ void pcm_set_frequency(unsigned int frequency) } /* pcm_set_frequency */ /* apply audio settings */ -void pcm_apply_settings(bool reset) +void _pcm_apply_settings(bool clear_reset) { - static int last_pcm_freq = HW_SAMPR_DEFAULT; - unsigned long output = IIS_CONFIG & (7 << 8); - - /* Playback must prevent pops and record monitoring won't work at all if - adding IIS_RESET when setting IIS_CONFIG. Use a different method for - each. */ - if (reset && output != (3 << 8)) - { - /* Not playback - reset first */ - SET_IIS_CONFIG(IIS_RESET); - reset = false; - } - + static int last_pcm_freq = 0; + if (pcm_freq != last_pcm_freq) { last_pcm_freq = pcm_freq; + /* Reprogramming bits 15-12 requires FIFO to be in a reset + condition - Users Manual 17-8, Note 11 */ + or_l(IIS_FIFO_RESET, &IIS_PLAY); audiohw_set_frequency(freq_ent[FPARM_FSEL]); coldfire_set_pllcr_audio_bits(PLLCR_SET_AUDIO_BITS_DEFPARM); } - SET_IIS_CONFIG(IIS_DEFPARM(output) | (reset ? IIS_RESET : 0)); + SET_IIS_PLAY(IIS_PLAY_DEFPARM | + (clear_reset ? 0 : (IIS_PLAY & IIS_FIFO_RESET))); +#if 0 + logf("IISPLAY: %08X", IIS_PLAY); +#endif +} /* _pcm_apply_settings */ + +/* This clears the reset bit to enable monitoring immediately */ +void pcm_apply_settings(void) +{ + _pcm_apply_settings(true); } /* pcm_apply_settings */ /** DMA **/ @@ -157,27 +159,31 @@ void pcm_play_dma_start(const void *addr, size_t size) /* Set up DMA transfer */ SAR0 = (unsigned long)addr; /* Source address */ DAR0 = (unsigned long)&PDOR3; /* Destination address */ - BCR0 = size; /* Bytes to transfer */ + BCR0 = (unsigned long)size; /* Bytes to transfer */ /* Enable the FIFO and force one write to it */ - pcm_apply_settings(false); + pcm_apply_settings(); DCR0 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | - DMA_SINC | DMA_SSIZE(3) | DMA_START; + DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE) | DMA_START; } /* pcm_play_dma_start */ /* Stops the DMA transfer and interrupt */ void pcm_play_dma_stop(void) { +#if 0 logf("pcm_play_dma_stop"); +#endif pcm_playing = false; - DCR0 = 0; DSR0 = 1; + DCR0 = 0; - /* Reset the FIFO */ - pcm_apply_settings(false); + /* Place FIFO in reset condition */ + or_l(IIS_FIFO_RESET, &IIS_PLAY); + + pcm_playing = false; } /* pcm_play_dma_stop */ void pcm_init(void) @@ -188,17 +194,26 @@ void pcm_init(void) pcm_paused = false; pcm_callback_for_more = NULL; + AUDIOGLOB = (1 << 8) /* IIS1 fifo auto sync */ + | (1 << 7) /* PDIR2 fifo auto sync */ +#ifdef HAVE_SPDIF_OUT + | (1 << 10) /* EBU TX auto sync */ +#endif + ; DIVR0 = 54; /* DMA0 is mapped into vector 54 in system.c */ - DMAROUTE = (DMAROUTE & 0xffffff00) | DMA0_REQ_AUDIO_1; + and_l(0xffffff00, &DMAROUTE); + or_l(DMA0_REQ_AUDIO_1, &DMAROUTE); DMACONFIG = 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */ - /* Reset the audio FIFO */ - SET_IIS_CONFIG(IIS_RESET); - + /* Call pcm_play_dma_stop to initialize everything. */ + pcm_play_dma_stop(); + /* Call pcm_close_recording to put in closed state */ + pcm_close_recording(); + audio_set_output_source(AUDIO_SRC_PLAYBACK); + audio_set_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK); pcm_set_frequency(HW_FREQ_DEFAULT); - /* Prevent pops (resets DAC to zero point) */ - SET_IIS_CONFIG(IIS_DEFPARM(3 << 8) | IIS_RESET); + _pcm_apply_settings(false); #if defined(HAVE_SPDIF_IN) || defined(HAVE_SPDIF_OUT) spdif_init(); @@ -221,12 +236,9 @@ void pcm_init(void) (DAC should be at zero point now). */ audiohw_mute(false); - /* Call pcm_play_dma_stop to initialize everything. */ - pcm_play_dma_stop(); - /* Enable interrupt at level 7, priority 0 */ ICR6 = (7 << 2); - IMR &= ~(1 << 14); /* bit 14 is DMA0 */ + and_l(~(1 << 14), &IMR); /* bit 14 is DMA0 */ } /* pcm_init */ size_t pcm_get_bytes_waiting(void) @@ -241,9 +253,8 @@ void DMA0(void) { int res = DSR0; - DSR0 = 1; /* Clear interrupt */ - DCR0 &= ~DMA_EEXT; - + DSR0 = 1; /* Clear interrupt */ + and_l(~DMA_EEXT, &DCR0); /* Disable peripheral request */ /* Stop on error */ if ((res & 0x70) == 0) { @@ -258,7 +269,7 @@ void DMA0(void) { SAR0 = (unsigned long)next_start; /* Source address */ BCR0 = next_size; /* Bytes to transfer */ - DCR0 |= DMA_EEXT; + or_l(DMA_EEXT, &DCR0); /* Enable peripheral request */ return; } else @@ -272,7 +283,13 @@ void DMA0(void) } else { - logf("DMA Error:0x%04x", res); + logf("DMA0 err: %02x", res); +#if 0 + logf(" SAR0: %08x", SAR0); + logf(" DAR0: %08x", DAR0); + logf(" BCR0: %08x", BCR0); + logf(" DCR0: %08x", DCR0); +#endif } pcm_play_dma_stop(); @@ -290,7 +307,10 @@ void pcm_rec_dma_start(void *addr, size_t size) pcm_recording = true; - pcm_apply_settings(false); + and_l(~PDIR2_FIFO_RESET, &DATAINCONTROL); + /* Clear reset bit if the source is not set to monitor playback + otherwise maintain independence between playback and recording. */ + _pcm_apply_settings((IIS_PLAY & (7 << 8)) != (3 << 8)); /* Start the DMA transfer.. */ #ifdef HAVE_SPDIF_IN @@ -303,7 +323,7 @@ void pcm_rec_dma_start(void *addr, size_t size) BCR1 = (unsigned long)size; /* Bytes to transfer */ DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | DMA_DINC | - DMA_DSIZE(3) | DMA_START; + DMA_DSIZE(DMA_SIZE_LINE) /* | DMA_START */; } /* pcm_dma_start */ void pcm_rec_dma_stop(void) @@ -314,6 +334,7 @@ void pcm_rec_dma_stop(void) DCR1 = 0; pcm_recording = false; + or_l(PDIR2_FIFO_RESET, &DATAINCONTROL); } /* pcm_dma_stop */ void pcm_init_recording(void) @@ -323,16 +344,15 @@ void pcm_init_recording(void) pcm_recording = false; pcm_callback_more_ready = NULL; - AUDIOGLOB |= 0x180; /* IIS1 fifo auto sync = on, PDIR2 auto sync = on */ - - DIVR1 = 55; /* DMA1 is mapped into vector 55 in system.c */ - DMACONFIG = 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */ - DMAROUTE = (DMAROUTE & 0xffff00ff) | DMA1_REQ_AUDIO_2; + DIVR1 = 55; /* DMA1 is mapped into vector 55 in system.c */ + DMACONFIG = 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */ + and_l(0xffff00ff, &DMAROUTE); + or_l(DMA1_REQ_AUDIO_2, &DMAROUTE); pcm_rec_dma_stop(); - ICR7 = (7 << 2); /* Enable interrupt at level 7, priority 0 */ - IMR &= ~(1 << 15); /* bit 15 is DMA1 */ + ICR7 = (7 << 2); /* Enable interrupt at level 7, priority 0 */ + and_l(~(1 << 15), &IMR); /* bit 15 is DMA1 */ } /* pcm_init_recording */ void pcm_close_recording(void) @@ -341,9 +361,9 @@ void pcm_close_recording(void) pcm_rec_dma_stop(); - DMAROUTE &= 0xffff00ff; - ICR7 = 0x00; /* Disable interrupt */ - IMR |= (1 << 15); /* bit 15 is DMA1 */ + and_l(0xffff00ff, &DMAROUTE); + ICR7 = 0x00; /* Disable interrupt */ + or_l((1 << 15), &IMR); /* bit 15 is DMA1 */ } /* pcm_close_recording */ /* DMA1 Interrupt is called when the DMA has finished transfering a chunk @@ -355,13 +375,19 @@ void DMA1(void) int status = 0; pcm_more_callback_type2 more_ready; - DSR1 = 1; /* Clear interrupt */ - DCR1 &= ~DMA_EEXT; /* Disable peripheral request */ + DSR1 = 1; /* Clear interrupt */ + and_l(~DMA_EEXT, &DCR1); /* Disable peripheral request */ if (res & 0x70) { status = DMA_REC_ERROR_DMA; - logf("DMA1 err: 0x%x", res); + logf("DMA1 err: %02x", res); +#if 0 + logf(" SAR1: %08x", SAR1); + logf(" DAR1: %08x", DAR1); + logf(" BCR1: %08x", BCR1); + logf(" DCR1: %08x", DCR1); +#endif } #ifdef HAVE_SPDIF_IN else if (DATAINCONTROL == 0xc038 && @@ -392,7 +418,7 @@ void pcm_record_more(void *start, size_t size) rec_peak_addr = (unsigned long *)start; /* Start peaking at dest */ DAR1 = (unsigned long)start; /* Destination address */ BCR1 = (unsigned long)size; /* Bytes to transfer */ - DCR1 |= DMA_EEXT; + or_l(DMA_EEXT, &DCR1); /* Enable peripheral request */ } void pcm_mute(bool mute) @@ -405,15 +431,15 @@ void pcm_mute(bool mute) void pcm_play_pause_pause(void) { /* Disable DMA peripheral request. */ - DCR0 &= ~DMA_EEXT; - pcm_apply_settings(true); + and_l(~DMA_EEXT, &DCR0); + or_l(IIS_FIFO_RESET, &IIS_PLAY); } /* pcm_play_pause_pause */ void pcm_play_pause_unpause(void) { /* Enable the FIFO and force one write to it */ - pcm_apply_settings(false); - DCR0 |= DMA_EEXT | DMA_START; + pcm_apply_settings(); + or_l(DMA_EEXT | DMA_START, &DCR0); } /* pcm_play_pause_unpause */ /** diff --git a/firmware/target/coldfire/system-coldfire.c b/firmware/target/coldfire/system-coldfire.c index bc769877ba..251c97fb73 100644 --- a/firmware/target/coldfire/system-coldfire.c +++ b/firmware/target/coldfire/system-coldfire.c @@ -321,3 +321,8 @@ void coldfire_set_pllcr_audio_bits(long bits) PLLCR = (PLLCR & ~0x70400000) | (bits & 0x70400000); } +/* Set DATAINCONTROL without disturbing FIFO reset state */ +void coldfire_set_dataincontrol(unsigned long value) +{ + DATAINCONTROL = (DATAINCONTROL & (1 << 9)) | value; +} diff --git a/firmware/target/coldfire/system-target.h b/firmware/target/coldfire/system-target.h index d02f835540..31947a2883 100644 --- a/firmware/target/coldfire/system-target.h +++ b/firmware/target/coldfire/system-target.h @@ -143,6 +143,9 @@ static inline void invalidate_icache(void) #define DEFAULT_PLLCR_AUDIO_BITS 0x10400000 void coldfire_set_pllcr_audio_bits(long bits); +/* Set DATAINCONTROL without disturbing FIFO reset state */ +void coldfire_set_dataincontrol(unsigned long value); + /* 11.2896 MHz */ #define CPUFREQ_DEFAULT_MULT 1 #define CPUFREQ_DEFAULT (CPUFREQ_DEFAULT_MULT * CPU_FREQ)