From 14e80671afca494b26354753c8fddc3c3a787d4c Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Sat, 6 Aug 2005 10:12:19 +0000 Subject: iAudio: First unfinished attempt for tlv320 driver and rockbox integration git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7286 a1c6a512-1295-4272-9138-f99709370657 --- apps/pcm_recording.c | 79 ++++++++++------ firmware/SOURCES | 4 +- firmware/drivers/tlv320.c | 223 ++++++++++++++++++++++++++++++++++++++++++++++ firmware/export/tlv320.h | 19 ++-- firmware/pcm_playback.c | 56 +++++++++--- firmware/pcm_record.c | 194 +++++++++++++++++++++------------------- firmware/powermgmt.c | 6 +- firmware/sound.c | 2 + 8 files changed, 441 insertions(+), 142 deletions(-) create mode 100644 firmware/drivers/tlv320.c diff --git a/apps/pcm_recording.c b/apps/pcm_recording.c index 67f7d4d..9df44a5 100644 --- a/apps/pcm_recording.c +++ b/apps/pcm_recording.c @@ -48,10 +48,14 @@ #include "sound.h" #include "ata.h" #include "logf.h" +#if defined(HAVE_UDA1380) #include "uda1380.h" +#elif defined(HAVE_TLV320) +#include "tlv320.h" +#endif #include "pcm_record.h" -#ifdef HAVE_UDA1380 +#if defined(HAVE_UDA1380) || defined(HAVE_TLV320) bool pcm_rec_screen(void) { @@ -64,36 +68,45 @@ bool pcm_rec_screen(void) int rec_time; int done, button; int w, h; - + lcd_setfont(FONT_SYSFIXED); lcd_getstringsize("M", &w, &h); lcd_setmargins(global_settings.invert_cursor ? 0 : w, 8); - - play_vol = 120; + + play_vol = 120; //cpu_boost(true); +#if defined(HAVE_UDA1380) uda1380_enable_output(true); +#elif defined(HAVE_TLV320) + tlv320_enable_output(true); +#endif + +#if defined(HAVE_UDA1380) uda1380_set_master_vol(play_vol, play_vol); - +#elif defined(HAVE_TLV320) + tlv320_set_headphone_vol(play_vol, play_vol); +#endif + rec_monitor = 0; // No record feedback rec_source = 1; // Mic rec_gain = 0; // 0-15 rec_vol = 0; // 0-255 rec_count = 0; rec_waveform = 0; - + pcm_open_recording(); pcm_set_recording_options(rec_source, rec_waveform); pcm_set_recording_gain(rec_gain, rec_vol); - + //rec_create_directory(); - + done = 0; while(!done) { line = 0; - + snprintf(buf, sizeof(buf), "PlayVolume: %3d", play_vol); lcd_puts(0,line++, buf); snprintf(buf, sizeof(buf), "Gain : %2d Volume : %2d", rec_gain, rec_vol); @@ -112,10 +125,10 @@ bool pcm_rec_screen(void) snprintf(buf, sizeof(buf), "File : %s", filename); lcd_puts(0,line++, buf); snprintf(buf, sizeof(buf), "Time : %02d:%02d.%02d", rec_time/HZ/60, (rec_time/HZ)%60, rec_time%HZ); - lcd_puts(0,line++, buf); - + lcd_puts(0,line++, buf); + line++; - + snprintf(buf, sizeof(buf), "MODE : Select source"); lcd_puts(0,line++, buf); snprintf(buf, sizeof(buf), "UP/DOWN : Record volume"); @@ -127,10 +140,10 @@ bool pcm_rec_screen(void) snprintf(buf, sizeof(buf), "RMT PLAY: Toggle waveform"); lcd_puts(0,line++, buf); - + lcd_update(); - - + + button = button_get_w_tmo(HZ/8); switch (button) { @@ -142,14 +155,14 @@ bool pcm_rec_screen(void) if (pcm_status() & AUDIO_STATUS_RECORD) { pcm_stop_recording(); - + } else { snprintf(filename, MAX_PATH, "/record-%0d.wav", rec_count++); pcm_record(filename); } break; - + case BUTTON_ON: break; @@ -162,7 +175,7 @@ bool pcm_rec_screen(void) case BUTTON_RIGHT | BUTTON_REPEAT: if (rec_gain < 15) rec_gain++; - + pcm_set_recording_gain(rec_gain, rec_vol); break; @@ -170,20 +183,22 @@ bool pcm_rec_screen(void) case BUTTON_LEFT | BUTTON_REPEAT: if (rec_gain > 0) rec_gain--; - + pcm_set_recording_gain(rec_gain, rec_vol); break; - + case BUTTON_RC_MENU: rec_monitor = 1 - rec_monitor; +#if defined(HAVE_UDA1380) uda1380_set_monitor(rec_monitor); +#endif break; - + case BUTTON_RC_ON: rec_waveform = 1 - rec_waveform; pcm_set_recording_options(rec_source, rec_waveform); break; - + case BUTTON_UP: case BUTTON_UP | BUTTON_REPEAT: if (rec_vol<255) @@ -205,23 +220,29 @@ bool pcm_rec_screen(void) } else { pcm_stop_recording(); - +#if defined(HAVE_UDA1380) uda1380_enable_output(false); - +#elif defined(HAVE_TLV320) + tlv320_enable_output(false); +#endif default_event_handler(SYS_USB_CONNECTED); return false; } break; - + } - + } - + pcm_stop_recording(); pcm_close_recording(); - + +#if defined(HAVE_UDA1380) uda1380_enable_output(false); - +#elif defined(HAVE_TLV320) + tlv320_enable_output(false); +#endif + return true; } diff --git a/firmware/SOURCES b/firmware/SOURCES index 937bb0b..be471fb 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -126,6 +126,8 @@ drivers/lcd-h100-remote.c #endif #if defined(HAVE_UDA1380) && !defined(SIMULATOR) drivers/uda1380.c +#elif defined(HAVE_TLV320) && !defined(SIMULATOR) +drivers/tlv320.c #endif #if (CONFIG_HWCODEC == MASNONE) && !defined(SIMULATOR) pcm_playback.c @@ -133,7 +135,7 @@ pcm_playback.c #if CONFIG_HWCODEC == MASNONE replaygain.c #endif -#if defined(HAVE_UDA1380) && !defined(SIMULATOR) +#if defined(CPU_COLDFIRE) && !defined(SIMULATOR) pcm_record.c #endif sound.c diff --git a/firmware/drivers/tlv320.c b/firmware/drivers/tlv320.c new file mode 100644 index 0000000..bafd77c --- /dev/null +++ b/firmware/drivers/tlv320.c @@ -0,0 +1,223 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2005 by Christian Gmeiner + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "lcd.h" +#include "cpu.h" +#include "kernel.h" +#include "thread.h" +#include "power.h" +#include "debug.h" +#include "system.h" +#include "sprintf.h" +#include "button.h" +#include "string.h" +#include "file.h" +#include "buffer.h" + +#include "i2c-coldfire.h" +#include "tlv320.h" + +/* local functions and definations */ +#define TLV320_ADDR 0x34 + +struct tlv320_info +{ + int vol_l; + int vol_r; +} tlv320; + +/* Definition of a playback configuration to start with */ +#define NUM_DEFAULT_REGS 10 +unsigned tlv320_defaults[2*NUM_DEFAULT_REGS] = +{ + REG_PC, PC_ON | PC_OSC | PC_CLK | PC_DAC | ~PC_OUT, /* do we need to enable osciliator and clock? */ + REG_LLIV, LLIV_LIM, /* mute adc input */ + REG_RLIV, RLIV_RIM, /* mute adc input */ + REG_LHV, LHV_LHV(HEADPHONE_MUTE), /* mute headphone */ + REG_RHV, RHV_RHV(HEADPHONE_MUTE), /* mute headphone */ + REG_AAP, AAP_MICM, /* mute microphone */ + REG_DAP, DAP_DEEMP_DIS, /* de-emphasis control: disabled */ + REG_DAIF, DAIF_FOR_I2S | DAIF_IWL_24 | ~DAIF_MS, /* i2s with 24 bit data len and slave mode */ + REG_SRC, 0, /* ToDo */ + REG_DIA, DIA_ACT, /* activate digital interface */ +}; +unsigned tlv320_regs[0xf]; + +void tlv320_write_reg(unsigned reg, unsigned value) +{ + unsigned data[3]; + + data[0] = TLV320_ADDR; + data[1] = reg << 1; + data[2] = value & 0xff; + + if (i2c_write(1, data, 3) != 3) + { + DEBUGF("tlv320 error reg=0x%x", reg); + return; + } + + tlv320_regs[reg] = value; +} + +/* Returns 0 if successful or -1 if some register failed */ +void tlv320_set_regs() +{ + int i; + memset(tlv320_regs, 0, sizeof(tlv320_regs)); + + /* Initialize all registers */ + for (i=0; i> 8); } - + logf("pcm_open_rec done"); } @@ -162,10 +166,10 @@ void pcm_close_recording(void) unsigned long pcm_status(void) { unsigned long ret = 0; - + if (is_recording) ret |= AUDIO_STATUS_RECORD; - + return ret; } @@ -193,7 +197,7 @@ unsigned long pcm_recorded_time(void) unsigned long pcm_num_recorded_bytes(void) { - + if (is_recording) { return num_rec_bytes; @@ -222,10 +226,12 @@ void pcm_resume_recording(void) */ void pcm_set_recording_options(int source, bool enable_waveform) { +#if defined(HAVE_UDA1380) uda1380_enable_recording(source); - +#elif defined(HAVE_TLV320) + tlv320_enable_recording(source); +#endif show_waveform = enable_waveform; - } @@ -238,21 +244,20 @@ void pcm_set_recording_gain(int gain, int volume) { rec_gain = gain; rec_volume = volume; - + queue_post(&pcmrec_queue, PCMREC_SET_GAIN, 0); - } - + /** * Start recording * * Use pcm_set_recording_options before calling record - */ + */ void pcm_record(const char *filename) { strncpy(recording_filename, filename, MAX_PATH - 1); recording_filename[MAX_PATH - 1] = 0; - + queue_post(&pcmrec_queue, PCMREC_START, 0); } @@ -263,19 +268,17 @@ void pcm_stop_recording(void) { if (is_recording) is_stopping = 1; - + queue_post(&pcmrec_queue, PCMREC_STOP, 0); logf("pcm_stop_recording"); - + while (is_stopping) { sleep(HZ >> 4); } - + logf("pcm_stop_recording done"); - - } @@ -303,40 +306,40 @@ void pcmrec_callback(bool flush) num_ready += NUM_BUFFERS; /* we can consume up to num_ready buffers */ - -#ifdef HAVE_REMOTE_LCD + +#ifdef HAVE_REMOTE_LCD /* Draw waveform on remote LCD */ - if (show_waveform && num_ready>0) + if (show_waveform && num_ready>0) { short *buf; long x,y,offset; int show_index; /* Just display the last buffer (most recent one) */ - show_index = read_index + num_ready - 1; + show_index = read_index + num_ready - 1; buf = (short*)rec_buffers[show_index]; - + lcd_remote_clear_display(); - + offset = 0; for (x=0; x> 15; /* Divide with SHRT_MAX */ y += LCD_REMOTE_HEIGHT/2; - + if (y < 2) y=2; if (y >= LCD_REMOTE_HEIGHT-2) y = LCD_REMOTE_HEIGHT-2; - + lcd_remote_drawpixel(x,y); - + offset += (EACH_BUFFER_SIZE/2) / LCD_REMOTE_WIDTH; } - - lcd_remote_update(); + + lcd_remote_update(); } - -#endif + +#endif /* Note: This might be a good place to call the 'codec' later */ @@ -348,43 +351,41 @@ void pcmrec_callback(bool flush) { unsigned long *ptr = (unsigned long*)rec_buffers[read_index]; int i; - + for (i=0; i= NUM_BUFFERS) read_index -= NUM_BUFFERS; } - + } else { /* In this case we must consume the buffers otherwise we will */ /* get 'dma1 overrun' pretty fast */ - + read_index+=num_ready; if (read_index >= NUM_BUFFERS) read_index -= NUM_BUFFERS; } } - - void pcmrec_dma_start(void) { DAR1 = (unsigned long)rec_buffers[write_index++]; /* Destination address */ SAR1 = (unsigned long)&PDIR2; /* Source address */ BCR1 = EACH_BUFFER_SIZE; /* Bytes to transfer */ - + /* Start the DMA transfer.. */ - DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_DINC | DMA_START; - + DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_DINC | DMA_START; + logf("dma1 started"); } @@ -396,7 +397,7 @@ void DMA1(void) int res = DSR1; DSR1 = 1; /* Clear interrupt */ - + int_count++; if (res & 0x70) @@ -404,41 +405,41 @@ void DMA1(void) DCR1 = 0; /* Stop DMA transfer */ error_count++; is_recording = 0; - + logf("dma1 err 0x%x", res); - + } else { num_rec_bytes += EACH_BUFFER_SIZE; - + write_index++; if (write_index >= NUM_BUFFERS) write_index = 0; - + if (is_stopping || !is_recording) { DCR1 = 0; /* Stop DMA transfer */ is_recording = 0; - + logf("dma1 stopping"); - + } else if (write_index == read_index) { DCR1 = 0; /* Stop DMA transfer */ is_recording = 0; - + logf("dma1 overrun"); - + } else { DAR1 = (unsigned long)rec_buffers[write_index]; /* Destination address */ BCR1 = EACH_BUFFER_SIZE; queue_post(&pcmrec_queue, PCMREC_GOT_DATA, NULL); - + } } - + IPR |= (1<<15); /* Clear pending interrupt request */ } @@ -450,7 +451,7 @@ static int start_wave(void) 0x10,0,0,0,1,0,2,0,0x44,0xac,0,0,0x10,0xb1,2,0, 4,0,0x10,0,'d','a','t','a',0,0,0,0 }; - + wav_file = open(recording_filename, O_RDWR|O_CREAT|O_TRUNC); if (wav_file < 0) { @@ -458,7 +459,7 @@ static int start_wave(void) logf("create failed: %d", wav_file); return -1; } - + if (sizeof(header) != write(wav_file, header, sizeof(header))) { close(wav_file); @@ -466,7 +467,7 @@ static int start_wave(void) logf("write failed"); return -2; } - + return 0; } @@ -474,15 +475,15 @@ static int start_wave(void) static void close_wave(void) { long l; - + l = SWAB32(num_rec_bytes + 36); lseek(wav_file, 4, SEEK_SET); write(wav_file, &l, 4); - + l = SWAB32(num_rec_bytes); lseek(wav_file, 40, SEEK_SET); write(wav_file, &l, 4); - + close(wav_file); wav_file = -1; } @@ -490,19 +491,19 @@ static void close_wave(void) static void pcmrec_start(void) { logf("pcmrec_start"); - + if (is_recording) return; - + if (wav_file != -1) close(wav_file); - + logf("rec: %s", recording_filename); - + start_wave(); /* todo: send signal to pcm_record if we have failed */ num_rec_bytes = 0; - + /* Store the current time */ record_start_time = current_tick; @@ -514,29 +515,29 @@ static void pcmrec_start(void) is_recording = 1; pcmrec_dma_start(); - + } static void pcmrec_stop(void) { /* wait for recording to finish */ - + /* todo: Abort current DMA transfer using DCR1.. */ - + logf("pcmrec_stop"); - + while (is_recording) { sleep(HZ >> 4); } - + logf("pcmrec_stop done"); /* Write unfinished buffers to file */ - pcmrec_callback(true); + pcmrec_callback(true); close_wave(); - + is_stopping = 0; } @@ -544,7 +545,7 @@ static void pcmrec_open(void) { unsigned long buffer_start; int i; - + show_waveform = 0; is_recording = 0; is_stopping = 0; @@ -555,7 +556,7 @@ static void pcmrec_open(void) buffer_start = (unsigned long)(&audiobuf[(audiobufend - audiobuf) - (ALL_BUFFERS_SIZE + 16)]); buffer_start &= ~3; - + for (i=0; i