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
This commit is contained in:
Michael Sevakis 2007-03-05 08:14:27 +00:00
parent 9701954654
commit 8867d00141
10 changed files with 123 additions and 101 deletions

View file

@ -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;

View file

@ -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,

View file

@ -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 */

View file

@ -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)

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */
/**

View file

@ -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;
}

View file

@ -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)