Index: apps/plugins/plugin.lds =================================================================== RCS file: /cvsroot/rockbox/apps/plugins/plugin.lds,v retrieving revision 1.27 diff -u -r1.27 plugin.lds --- apps/plugins/plugin.lds 12 Jan 2006 00:35:49 -0000 1.27 +++ apps/plugins/plugin.lds 22 Jan 2006 18:12:47 -0000 @@ -20,7 +20,7 @@ #define ARCH_IRIVER #endif -#if CONFIG_CPU==PP5020 +#if CONFIG_CPU==PP5020 || CONFIG_CPU==PP5002 #define ARCH_IPOD #endif Index: bootloader/SOURCES =================================================================== RCS file: /cvsroot/rockbox/bootloader/SOURCES,v retrieving revision 1.2 diff -u -r1.2 SOURCES --- bootloader/SOURCES 8 Nov 2005 00:52:39 -0000 1.2 +++ bootloader/SOURCES 22 Jan 2006 18:12:47 -0000 @@ -1,4 +1,4 @@ -#if (CONFIG_CPU == PP5020) +#if (CONFIG_CPU == PP5020) || (CONFIG_CPU == PP5002) ipod.c #else main.c Index: bootloader/ipod.c =================================================================== RCS file: /cvsroot/rockbox/bootloader/ipod.c,v retrieving revision 1.6 diff -u -r1.6 ipod.c --- bootloader/ipod.c 5 Jan 2006 17:02:47 -0000 1.6 +++ bootloader/ipod.c 22 Jan 2006 18:12:47 -0000 @@ -39,11 +39,20 @@ #include "power.h" #include "file.h" -#define DRAM_START 0x10000000 -#define IPOD_PP5020_RTC 0x60005010 +#define IPOD_PP5020_RTC 0x60005010 +#define IPOD_PP5002_RTC 0xcf001110 +#if (CONFIG_CPU == PP5020) +#define DRAM_START 0x10000000 +#define IPOD_RTC 0x60005010 +#else +#define IPOD_RTC 0xcf001110 +#define IPOD_LCD_BASE 0xc0001000 +#define DRAM_START 0x28000000 +#endif #define IPOD_HW_REVISION (*((volatile unsigned long*)(0x00002084))) +#define BUTTON_HOLD 0 #define BUTTON_LEFT 1 #define BUTTON_MENU 2 #define BUTTON_RIGHT 3 @@ -98,13 +107,13 @@ /* get current usec counter */ int timer_get_current(void) { - return inl(IPOD_PP5020_RTC); + return inl(IPOD_RTC); } /* check if number of seconds has past */ int timer_check(int clock_start, unsigned int usecs) { - if ((inl(IPOD_PP5020_RTC) - clock_start) >= usecs) { + if ((inl(IPOD_RTC) - clock_start) >= usecs) { return 1; } else { return 0; @@ -114,9 +123,9 @@ /* This isn't a sleep, but let's call it that. */ int usleep(unsigned int usecs) { - unsigned int start = inl(IPOD_PP5020_RTC); + unsigned int start = inl(IPOD_RTC); - while ((inl(IPOD_PP5020_RTC) - start) < usecs) { + while ((inl(IPOD_RTC) - start) < usecs) { // empty } @@ -201,11 +210,22 @@ { unsigned char state; - state = opto_keypad_read(); + +#if CONFIG_CPU == PP5020 + state = opto_keypad_read(); if ((state & 0x4) == 0) return BUTTON_LEFT; if ((state & 0x10) == 0) return BUTTON_MENU; if ((state & 0x8) == 0) return BUTTON_PLAY; if ((state & 0x2) == 0) return BUTTON_RIGHT; +#else + /** For iPod 3G **/ + state = inb(0xcf000030); + if (((state & 0x20) == 0)) return BUTTON_HOLD; /* hold on */ + if ((state & 0x08) == 0) return BUTTON_LEFT; + if ((state & 0x10) == 0) return BUTTON_MENU; + if ((state & 0x04) == 0) return BUTTON_PLAY; + if ((state & 0x01) == 0) return BUTTON_RIGHT; +#endif return 0; } @@ -333,7 +353,9 @@ /* set port L07 on */ outl(((0x100 | 1) << 7), 0x6000d12c); - +#elif CONFIG_BACKLIGHT==BL_IPOD3G +int lcd_state; + outl(inl(IPOD_LCD_BASE) | 0x2, IPOD_LCD_BASE); #endif system_init(); Index: firmware/SOURCES =================================================================== RCS file: /cvsroot/rockbox/firmware/SOURCES,v retrieving revision 1.62 diff -u -r1.62 SOURCES --- firmware/SOURCES 12 Jan 2006 00:35:50 -0000 1.62 +++ firmware/SOURCES 22 Jan 2006 18:12:47 -0000 @@ -50,7 +50,7 @@ #ifdef HAVE_LCD_BITMAP arabjoin.c bidi.c -#if LCD_DEPTH == 2 +#if LCD_DEPTH == 2 && !CONFIG_LCD==LCD_IPOD2BPP drivers/lcd-h100.c #elif LCD_DEPTH == 1 drivers/lcd-recorder.c @@ -58,12 +58,15 @@ drivers/lcd-16bit.c #endif #endif -#if CONFIG_LCD==LCD_IPODNANO || CONFIG_LCD==LCD_IPODCOLOR +#if CONFIG_LCD==LCD_IPODNANO || CONFIG_LCD==LCD_IPODCOLOR || CONFIG_LCD==LCD_IPOD2BPP drivers/lcd-ipod.c #endif #if CONFIG_LCD==LCD_IPODVIDEO drivers/lcd-ipodvideo.c #endif +#if CONFIG_LCD==LCD_IPOD2BPP +drivers/lcd-ipod2bpp.c +#endif #if CONFIG_LCD==LCD_H300 drivers/lcd-h300.c #endif @@ -97,6 +100,8 @@ drivers/i2c-coldfire.c #elif CONFIG_I2C == I2C_PP5020 drivers/i2c-pp5020.c +#elif CONFIG_I2C == I2C_PP5002 +drivers/i2c-pp5002.c #elif CONFIG_I2C == I2C_PNX0101 drivers/i2c-pnx0101.c #else @@ -108,7 +113,7 @@ #ifdef IRIVER_H300_SERIES drivers/pcf50606.c #endif -#if defined(APPLE_IPODCOLOR) || defined(APPLE_IPODNANO) || defined(APPLE_IPODVIDEO) +#if defined(APPLE_IPODCOLOR) || defined(APPLE_IPODNANO) || defined(APPLE_IPODVIDEO) || || defined(APPLE_IPOD3G) drivers/pcf50605.c #endif #if (CONFIG_RTC == RTC_M41ST84W) || (CONFIG_RTC == RTC_PCF50606) @@ -154,6 +159,8 @@ drivers/uda1380.c #elif defined(HAVE_WM8975) && !defined(SIMULATOR) drivers/wm8975.c +#elif defined(HAVE_WM8731L) && !defined(SIMULATOR) +drivers/wm8731l.c #elif defined(HAVE_TLV320) && !defined(SIMULATOR) drivers/tlv320.c #endif Index: firmware/backlight.c =================================================================== RCS file: /cvsroot/rockbox/firmware/backlight.c,v retrieving revision 1.69 diff -u -r1.69 backlight.c --- firmware/backlight.c 12 Jan 2006 00:35:50 -0000 1.69 +++ firmware/backlight.c 22 Jan 2006 18:12:48 -0000 @@ -242,6 +242,8 @@ /* set port L07 on */ outl(((0x100 | 1) << 7), 0x6000d12c); +#elif CONFIG_BACKLIGHT==BL_IPOD3G + lcd_enable(true); #elif CONFIG_BACKLIGHT==BL_IRIVER_IFP7XX GPIO3_SET = 1; #endif @@ -283,6 +285,8 @@ outl(((0x100 | 0) << 7), 0x6000d12c); #elif CONFIG_BACKLIGHT==BL_IRIVER_IFP7XX GPIO3_CLR = 1; +#elif CONFIG_BACKLIGHT==BL_IPOD3G + lcd_enable(false); #endif } Index: firmware/boot.lds =================================================================== RCS file: /cvsroot/rockbox/firmware/boot.lds,v retrieving revision 1.12 diff -u -r1.12 boot.lds --- firmware/boot.lds 6 Dec 2005 17:37:32 -0000 1.12 +++ firmware/boot.lds 22 Jan 2006 18:12:48 -0000 @@ -4,7 +4,7 @@ #ifdef CPU_COLDFIRE OUTPUT_FORMAT(elf32-m68k) INPUT(crt0.o) -#elif CONFIG_CPU == PP5020 +#elif CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002 OUTPUT_FORMAT(elf32-littlearm) OUTPUT_ARCH(arm) #else @@ -32,6 +32,12 @@ #define IRAMSIZE 0x18000 #define FLASHORIG 0x001f0000 #define FLASHSIZE 2M +#elif CONFIG_CPU == PP5002 +#define DRAMORIG 0x28000000 +#define IRAMORIG 0x40000000 +#define IRAMSIZE 0x18000 +#define FLASHORIG 0x001f0000 +#define FLASHSIZE 2M #else #define DRAMORIG 0x09000000 #define IRAMORIG 0x0f000000 @@ -40,7 +46,7 @@ #define FLASHSIZE 256K - ROM_START #endif -#if CONFIG_CPU!=PP5020 +#if CONFIG_CPU!=PP5020 && CONFIG_CPU!=PP5002 MEMORY { DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE @@ -50,7 +56,7 @@ #endif SECTIONS -#if CONFIG_CPU==PP5020 +#if CONFIG_CPU==PP5020 || CONFIG_CPU==PP5002 { . = IRAMORIG; Index: firmware/kernel.c =================================================================== RCS file: /cvsroot/rockbox/firmware/kernel.c,v retrieving revision 1.47 diff -u -r1.47 kernel.c --- firmware/kernel.c 12 Jan 2006 00:35:50 -0000 1.47 +++ firmware/kernel.c 22 Jan 2006 18:12:48 -0000 @@ -357,6 +357,46 @@ (void)interval_in_ms; #endif } +#elif CONFIG_CPU == PP5002 + +#define USECS_PER_INT 0x2710 + +#ifndef BOOTLOADER +void TIMER1(void) +{ + int i; + + PP5002_TIMER1_ACK; + /* Run through the list of tick tasks */ + for (i = 0;i < MAX_NUM_TICK_TASKS;i++) + { + if (tick_funcs[i]) + { + tick_funcs[i](); + } + } + + current_tick++; + wake_up_thread(); +} +#endif + +void tick_start(unsigned int interval_in_ms) +{ +#ifndef BOOTLOADER + /* TODO: use interval_in_ms to set timer periode */ + (void)interval_in_ms; + PP5002_TIMER1 = 0x0; + PP5002_TIMER1_ACK; + /* enable timer, period, trigger value 0x2710 -> 100Hz */ + PP5002_TIMER1 = 0xc0000000 | USECS_PER_INT; + /* unmask interrupt source */ + PP5002_CPU_INT_EN = PP5002_TIMER1_MASK; +#else + /* We don't enable interrupts in the bootloader */ + (void)interval_in_ms; +#endif +} #elif CONFIG_CPU == PNX0101 Index: firmware/pcm_playback.c =================================================================== RCS file: /cvsroot/rockbox/firmware/pcm_playback.c,v retrieving revision 1.80 diff -u -r1.80 pcm_playback.c --- firmware/pcm_playback.c 12 Jan 2006 00:35:50 -0000 1.80 +++ firmware/pcm_playback.c 22 Jan 2006 18:12:48 -0000 @@ -30,6 +30,8 @@ #include "wm8975.h" #elif defined(HAVE_TLV320) #include "tlv320.h" +#elif defined(HAVE_WM8731L) +#include "wm8731l.h" #endif #include "system.h" #endif @@ -487,6 +489,152 @@ return 0; } +#elif defined(HAVE_WM8731L) + +/* We need to unify this code with the uda1380 code as much as possible, but + we will keep it separate during early development. +*/ + +static bool pcm_playing; +static bool pcm_paused; +static int pcm_freq = 0x6; /* 44.1 is default */ + +static unsigned char *next_start; +static long next_size; + +/* Set up the DMA transfer that kicks in when the audio FIFO gets empty */ +static void dma_start(const void *addr, long size) +{ + pcm_playing = true; + + addr = (void *)((unsigned long)addr & ~3); /* Align data */ + size &= ~3; /* Size must be multiple of 4 */ + + /* Disable playback for now */ + pcm_playing = false; + return; + +/* This is the uda1380 code */ +#if 0 + /* Reset the audio FIFO */ + + /* Set up DMA transfer */ + SAR0 = ((unsigned long)addr); /* Source address */ + DAR0 = (unsigned long)&PDOR3; /* Destination address */ + BCR0 = size; /* Bytes to transfer */ + + /* Enable the FIFO and force one write to it */ + IIS2CONFIG = IIS_DEFPARM(pcm_freq); + + DCR0 = DMA_INT | DMA_EEXT | DMA_CS | DMA_SINC | DMA_START; +#endif +} + +/* Stops the DMA transfer and interrupt */ +static void dma_stop(void) +{ + pcm_playing = false; + +#if 0 +/* This is the uda1380 code */ + DCR0 = 0; + DSR0 = 1; + /* Reset the FIFO */ + IIS2CONFIG = IIS_RESET | IIS_DEFPARM(pcm_freq); +#endif + next_start = NULL; + next_size = 0; + pcm_paused = false; +} + + +void pcm_init(void) +{ + pcm_playing = false; + pcm_paused = false; + + /* Initialize default register values. */ + wm8731l_init(); + + /* The uda1380 needs a sleep(HZ) here - do we need one? */ + + /* Power on */ + wm8731l_enable_output(true); + + /* Unmute the master channel (DAC should be at zero point now). */ + wm8731l_mute(false); + + /* Call dma_stop to initialize everything. */ + dma_stop(); +} + +void pcm_set_frequency(unsigned int frequency) +{ + (void)frequency; + pcm_freq=frequency; +} + +/* the registered callback function to ask for more mp3 data */ +static void (*callback_for_more)(unsigned char**, long*) = NULL; + +void pcm_play_data(void (*get_more)(unsigned char** start, long* size)) +{ + unsigned char *start; + long size; + + callback_for_more = get_more; + + get_more((unsigned char **)&start, (long *)&size); + get_more(&next_start, &next_size); + + dma_start(start, size); +} + +void pcm_play_stop(void) +{ + if (pcm_playing) { + dma_stop(); + } +} + +void pcm_play_pause(bool play) +{ + if(pcm_paused && play && next_size) + { + logf("unpause"); + /* We need to enable DMA here */ + } + else if(!pcm_paused && !play) + { + logf("pause"); + /* We need to disable DMA here */ + } + pcm_paused = !play; +} + +bool pcm_is_paused(void) +{ + return pcm_paused; +} + +bool pcm_is_playing(void) +{ + return pcm_playing; +} + +void pcm_calculate_peaks(int *left, int *right) +{ + *left=0; + *right=0; +} + +long pcm_get_bytes_waiting(void) +{ + return 0; +} + + + #elif CONFIG_CPU == PNX0101 /* TODO: Implement for iFP7xx Index: firmware/system.c =================================================================== RCS file: /cvsroot/rockbox/firmware/system.c,v retrieving revision 1.81 diff -u -r1.81 system.c --- firmware/system.c 12 Jan 2006 00:35:50 -0000 1.81 +++ firmware/system.c 22 Jan 2006 18:12:49 -0000 @@ -1190,6 +1190,95 @@ (void)newmode; return 0; } +#elif CONFIG_CPU==PP5002 + +#ifndef BOOTLOADER +extern void TIMER1(void); +extern void ipod_3g_button_int(void); + +void irq(void) +{ + if (PP5002_CPU_INT_STAT & PP5002_TIMER1_MASK) + TIMER1(); + else if (PP5002_CPU_HI_INT_STAT & PP5002_I2C_MASK) + ipod_3g_button_int(); +} +#endif + +/* TODO: The following two function have been lifted straight from IPL, and + hence have a lot of numeric addresses used straight. I'd like to use + #defines for these, but don't know what most of them are for or even what + they should be named. Because of this I also have no way of knowing how + to extend the funtions to do alternate cache configurations and/or + some other CPU frequency scaling. */ + +#ifndef BOOTLOADER +static void ipod_init_cache(void) +{ +/* Initialising the cache in the iPod bootloader prevents Rockbox from starting */ + unsigned i; + outl(inl(0xcf004050) & ~0x700, 0xcf004050); + outl(0x4000, 0xcf004020); + + outl(0x2, 0xcf004024); + + /* PP5002 has 8KB cache */ + for (i = 0xf0004000; i < 0xf0006000; i += 16) { + outl(0x0, i); + } + + outl(0x0, 0xf000f020); + outl(0x3fc0, 0xf000f024); + + outl(0x3, 0xcf004024); +} + +static void ipod_set_cpu_speed(void) +{ + outl(0x02, 0xcf005008); + + outl(0x55, 0xcf00500c); + outl(0x6000, 0xcf005010); + + + // 75 MHz (24/24 * 75) (default) + outl(24, 0xcf005018); + outl(75, 0xcf00501c); +/* +#if 0 + // 66 MHz (24/3 * 8) + outl(3, 0xcf005018); + outl(8, 0xcf00501c); +#endif +*/ + outl(0xe000, 0xcf005010); + + udelay(2000); + + outl(0xa8, 0xcf00500c); +} +#endif + +void system_init(void) +{ +#ifndef BOOTLOADER + outl(-1, 0xcf00101c); + outl(-1, 0xcf001028); + outl(-1, 0xcf001038); + ipod_set_cpu_speed(); + ipod_init_cache(); +#endif +} + +void system_reboot(void) +{ +} + +int system_memory_guard(int newmode) +{ + (void)newmode; + return 0; +} #elif CONFIG_CPU==PNX0101 Index: firmware/thread.c =================================================================== RCS file: /cvsroot/rockbox/firmware/thread.c,v retrieving revision 1.56 diff -u -r1.56 thread.c --- firmware/thread.c 12 Jan 2006 00:35:50 -0000 1.56 +++ firmware/thread.c 22 Jan 2006 18:12:49 -0000 @@ -56,6 +56,16 @@ void *start; /* Thread start address */ int started; /* 0 when not started */ }; +#else +struct regs +{ + /** + * For Ipod3g + * TODO: Implement this reg struct + */ + void *start; /* Thread start address */ + +}; #endif #define DEADBEEF ((unsigned int)0xdeadbeef) @@ -237,6 +247,28 @@ \ } + + + +#elif CONFIG_CPU == PP5002 +/*--------------------------------------------------------------------------- + * Store non-volatile context. + *--------------------------------------------------------------------------- + */ +static inline void store_context(void* addr) +{ + /** TODO **/ +} + +/*--------------------------------------------------------------------------- + * Load non-volatile context. + *--------------------------------------------------------------------------- + */ +static inline void load_context(const void* addr) +{ + /** TODO **/ +} + #endif /*--------------------------------------------------------------------------- Index: firmware/drivers/ata.c =================================================================== RCS file: /cvsroot/rockbox/firmware/drivers/ata.c,v retrieving revision 1.163 diff -u -r1.163 ata.c --- firmware/drivers/ata.c 24 Nov 2005 00:51:57 -0000 1.163 +++ firmware/drivers/ata.c 22 Jan 2006 18:12:49 -0000 @@ -107,6 +107,42 @@ #define SET_REG(reg,val) reg = (val) #define SET_16BITREG(reg,val) reg = (val) +#elif CONFIG_CPU == PP5002 + +/* don't use sh7034 assembler routines */ +#define PREFER_C_READING +#define PREFER_C_WRITING + +#define ATA_IOBASE 0xc00031e0 +#define ATA_DATA (*((volatile unsigned short*)(ATA_IOBASE))) +#define ATA_ERROR (*((volatile unsigned char*)(ATA_IOBASE + 0x04))) +#define ATA_NSECTOR (*((volatile unsigned char*)(ATA_IOBASE + 0x08))) +#define ATA_SECTOR (*((volatile unsigned char*)(ATA_IOBASE + 0x0c))) +#define ATA_LCYL (*((volatile unsigned char*)(ATA_IOBASE + 0x10))) +#define ATA_HCYL (*((volatile unsigned char*)(ATA_IOBASE + 0x14))) +#define ATA_SELECT (*((volatile unsigned char*)(ATA_IOBASE + 0x18))) +#define ATA_COMMAND (*((volatile unsigned char*)(ATA_IOBASE + 0x1c))) +#define ATA_CONTROL (*((volatile unsigned char*)(0xc00033f8))) + +#define STATUS_BSY 0x80 +#define STATUS_RDY 0x40 +#define STATUS_DF 0x20 +#define STATUS_DRQ 0x08 +#define STATUS_ERR 0x01 +#define ERROR_ABRT 0x04 + +#define WRITE_PATTERN1 0xa5 +#define WRITE_PATTERN2 0x5a +#define WRITE_PATTERN3 0xaa +#define WRITE_PATTERN4 0x55 + +#define READ_PATTERN1 0xa5 +#define READ_PATTERN2 0x5a +#define READ_PATTERN3 0xaa +#define READ_PATTERN4 0x55 + +#define SET_REG(reg,val) reg = (val) +#define SET_16BITREG(reg,val) reg = (val) #elif CONFIG_CPU == SH7034 @@ -1245,7 +1281,7 @@ or_l(0x00040000, &GPIO_FUNCTION); #elif CONFIG_CPU == TCC730 -#elif CONFIG_CPU == PP5020 +#elif CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002 /* TODO: Implement ata_enable() */ (void)on; #endif @@ -1398,7 +1434,7 @@ bool coldstart = (P1 & 0x80) == 0; #elif CONFIG_CPU == MCF5249 bool coldstart = (GPIO_FUNCTION & 0x00080000) == 0; -#elif CONFIG_CPU == PP5020 +#elif CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002 bool coldstart = false; /* TODO: Implement coldstart variable */ #else @@ -1435,6 +1471,13 @@ outl(0x10, 0xc3000000); outl(0x80002150, 0xc3000004); +#elif CONFIG_CPU == PP5002 + /* From ipod-ide.c:ipod_ide_register() */ + outl(inl(0xc0003024) | (1 << 7), 0xc0003024); + outl(inl(0xc0003024) & ~(1<<2), 0xc0003024); + + outl(0x10, 0xc0003000); + outl(0x80002150, 0xc0003004); #endif sleeping = false; Index: firmware/drivers/button.c =================================================================== RCS file: /cvsroot/rockbox/firmware/drivers/button.c,v retrieving revision 1.107 diff -u -r1.107 button.c --- firmware/drivers/button.c 12 Jan 2006 00:35:50 -0000 1.107 +++ firmware/drivers/button.c 22 Jan 2006 18:12:50 -0000 @@ -61,7 +61,7 @@ #define REPEAT_INTERVAL_FINISH 5 /* the power-off button and number of repeated keys before shutting off */ -#if (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IRIVER_IFP7XX_PAD) +#if (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IRIVER_IFP7XX_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) #define POWEROFF_BUTTON BUTTON_PLAY #define POWEROFF_COUNT 40 #else @@ -210,12 +210,137 @@ outl(inl(0x7000c104) | 0xC000000, 0x7000c104); outl(0x400a1f00, 0x7000c100); + GPIOB_OUTPUT_VAL |= 0x10; PP5020_CPU_INT_EN = 0x40000000; PP5020_CPU_HI_INT_EN = PP5020_I2C_MASK; } #endif +#if CONFIG_KEYPAD == IPOD_3G_PAD +/* Variable to use for setting button status in interrupt handler */ +int int_btn = BUTTON_NONE; + +/** + * + * + */ +void handle_scroll_wheel(int new_scroll, int was_hold, int reverse) +{ + int wheel_keycode = BUTTON_NONE; + static int prev_scroll = -1; + static int scroll_state[4][4] = { + {0, 1, -1, 0}, + {-1, 0, 0, 1}, + {1, 0, 0, -1}, + {0, -1, 1, 0} + }; + + if ( prev_scroll == -1 ) { + prev_scroll = new_scroll; + } + else if (!was_hold) { + switch (scroll_state[prev_scroll][new_scroll]) { + case 1: + if (reverse) { + /* 'r' keypress */ + wheel_keycode = BUTTON_SCROLL_FWD; + } + else { + /* 'l' keypress */ + wheel_keycode = BUTTON_SCROLL_BACK; + } + break; + case -1: + if (reverse) { + /* 'l' keypress */ + wheel_keycode = BUTTON_SCROLL_BACK; + } + else { + /* 'r' keypress */ + wheel_keycode = BUTTON_SCROLL_FWD; + break; + default: + /* only happens if we get out of sync */ + break; + } + } + } + if (wheel_keycode != BUTTON_NONE) + queue_post(&button_queue, wheel_keycode, NULL); + prev_scroll = new_scroll; +} + +static int ipod_3g_button_read(void) +{ + unsigned char source, state; + static int was_hold = 0; +int btn = BUTTON_NONE; + /* + * we need some delay for g3, cause hold generates several interrupts, + * some of them delayed + */ + udelay(250); + + /* get source of interupts */ + source = inb(0xcf000040); + if (source) { + + /* get current keypad status */ + state = inb(0xcf000030); + outb(~state, 0xcf000060); + + if (was_hold && source == 0x40 && state == 0xbf) { + /* ack any active interrupts */ + outb(source, 0xcf000070); + return BUTTON_NONE; + } + was_hold = 0; + + + if ( source & 0x20 ) { + /* 3g hold switch is active low */ + btn |= BUTTON_HOLD; + was_hold = 1; + /* hold switch on 3g causes all outputs to go low */ + /* we shouldn't interpret these as key presses */ + goto done; + } + if (source & 0x1) { + btn |= BUTTON_RIGHT; + } + if (source & 0x2) { + btn |= BUTTON_SELECT; + } + if (source & 0x4) { + btn |= BUTTON_PLAY; + } + if (source & 0x8) { + btn |= BUTTON_LEFT; + } + if (source & 0x10) { + btn |= BUTTON_MENU; + } + + if (source & 0xc0) { + handle_scroll_wheel((state & 0xc0) >> 6, was_hold, 0); + } + done: + + /* ack any active interrupts */ + outb(source, 0xcf000070); + } + return btn; +} +void ipod_3g_button_int(void) +{ + /** + * Theire is other things to do but for now ... + * TODO: implement this function in a better way + **/ + int_btn = ipod_3g_button_read(); +} +#endif static void button_tick(void) { static int tick = 0; @@ -399,8 +524,12 @@ GPIOA_INT_EN = 0x20; PP5020_CPU_INT_EN = 0x40000000; PP5020_CPU_HI_INT_EN = PP5020_I2C_MASK; -#endif /* CONFIG_KEYPAD */ +#elif CONFIG_KEYPAD == IPOD_3G_PAD + outb(~inb(GPIOA_INPUT_VAL), GPIOA_INT_LEV); + outb(inb(GPIOA_INT_STAT), GPIOA_INT_CLR); + outb(0xff, GPIOA_INT_EN); +#endif /* CONFIG_KEYPAD */ queue_init(&button_queue); button_read(); lastbtn = button_read(); @@ -413,7 +542,7 @@ } #ifdef HAVE_LCD_BITMAP /* only bitmap displays can be flipped */ -#if (CONFIG_KEYPAD != IPOD_4G_PAD) +#if (CONFIG_KEYPAD != IPOD_4G_PAD) && (CONFIG_KEYPAD != IPOD_3G_PAD) /* * helper function to swap UP/DOWN, LEFT/RIGHT (and F1/F3 for Recorder) */ @@ -882,6 +1011,9 @@ (void)data; /* The int_btn variable is set in the button interrupt handler */ btn = int_btn; +#elif CONFIG_KEYPAD == IPOD_3G_PAD + (void)data; + btn = int_btn; #endif /* CONFIG_KEYPAD */ Index: firmware/drivers/lcd-ipod.c =================================================================== RCS file: /cvsroot/rockbox/firmware/drivers/lcd-ipod.c,v retrieving revision 1.8 diff -u -r1.8 lcd-ipod.c --- firmware/drivers/lcd-ipod.c 19 Dec 2005 14:30:52 -0000 1.8 +++ firmware/drivers/lcd-ipod.c 22 Jan 2006 18:12:50 -0000 @@ -32,10 +32,17 @@ /*** definitions ***/ #define IPOD_HW_REVISION (*((volatile unsigned long*)0x00002084)) #define IPOD_PP5020_RTC (*((volatile unsigned long*)0x60005010)) +#define IPOD_PP5002_RTC (*((volatile unsigned long*)0xcf001110)) +#if (CONFIG_LCD == LCD_IPODCOLOR) || (CONFIG_LCD == LCD_IPODNANO) #define IPOD_LCD_BASE 0x70008a0c #define IPOD_LCD_BUSY_MASK 0x80000000 - +#define IPOD_RTC (*((volatile unsigned long*)0x60005010)) +#elif CONFIG_LCD == LCD_IPOD2BPP +#define IPOD_LCD_BASE 0xc0001000 +#define IPOD_LCD_BUSY_MASK 0x80000000 +#define IPOD_RTC (*((volatile unsigned long*)0xcf001110)) +#endif /* LCD command codes for HD66789R */ #define LCD_CNTL_RAM_ADDR_SET 0x21 #define LCD_CNTL_WRITE_TO_GRAM 0x22 @@ -43,13 +50,21 @@ #define LCD_CNTL_VERT_RAM_ADDR_POS 0x45 /*** globals ***/ +#if (CONFIG_LCD == LCD_IPODCOLOR) || (CONFIG_LCD == LCD_IPODNANO) static int lcd_type = 1; /* 0 = "old" Color/Photo, 1 = "new" Color & Nano */ +#elif CONFIG_LCD == LCD_IPOD2BPP +static int lcd_type = 0; +#endif + +#define LCD_CMD 0x08 +#define LCD_DATA 0x10 +static unsigned int lcd_contrast = 0x6a; /* check if number of useconds has past */ static inline int timer_check(unsigned long clock_start, unsigned long usecs) { - if ( (IPOD_PP5020_RTC - clock_start) >= usecs ) { + if ( (IPOD_RTC - clock_start) >= usecs ) { return 1; } else { return 0; @@ -59,7 +74,7 @@ static void lcd_wait_write(void) { if ((inl(IPOD_LCD_BASE) & IPOD_LCD_BUSY_MASK) != 0) { - int start = IPOD_PP5020_RTC; + int start = IPOD_RTC; do { if ((inl(IPOD_LCD_BASE) & IPOD_LCD_BUSY_MASK) == 0) break; @@ -79,6 +94,15 @@ outl(v | 0x81000000, IPOD_LCD_BASE); } +/* send LCD data */ +static void lcd_send_data(int data_lo, int data_hi) +{ + lcd_wait_write(); + outl(data_lo, IPOD_LCD_BASE + LCD_DATA); + lcd_wait_write(); + outl(data_hi, IPOD_LCD_BASE + LCD_DATA); +} + static void lcd_cmd_data(int cmd, int data) { if (lcd_type == 0) { @@ -92,12 +116,35 @@ } } +static void lcd_prepare_cmd(int cmd) +{ + lcd_wait_write(); + outl(0x0, IPOD_LCD_BASE + LCD_CMD); + lcd_wait_write(); + outl(cmd, IPOD_LCD_BASE + LCD_CMD); + +} +/* send LCD command and data */ +/* this is only used for b&w lcds */ +static void lcd_cmd_and_data(int cmd, int data_lo, int data_hi) +{ + lcd_prepare_cmd(cmd); + lcd_send_data(data_lo, data_hi); +} + + + /*** hardware configuration ***/ void lcd_set_contrast(int val) { +#if CONFIG_LCD == LCD_IPOD2BPP + lcd_cmd_and_data(0x4, 0x4, val); + lcd_contrast = val; +#elif (CONFIG_LCD == LCD_IPODCOLOR) || (CONFIG_LCD == LCD_IPODNANO) /* TODO: Implement lcd_set_contrast() */ (void)val; +#endif } void lcd_set_invert_display(bool yesno) @@ -166,6 +213,22 @@ } #elif CONFIG_LCD == LCD_IPODNANO /* iPodLinux doesn't appear have any LCD init code for the Nano */ + +#elif CONFIG_LCD == LCD_IPOD2BPP + /* driver output control - 160x128 */ + outl(0x0, IPOD_LCD_BASE + LCD_CMD); + lcd_wait_write(); + outl(0x1, IPOD_LCD_BASE + LCD_CMD); + outl(0x1, IPOD_LCD_BASE + LCD_DATA); + lcd_wait_write(); + outl(0xf, IPOD_LCD_BASE + LCD_DATA); + + outl(0x0, IPOD_LCD_BASE + LCD_CMD); + lcd_wait_write(); + outl(0x5, IPOD_LCD_BASE + LCD_CMD); + outl(0x0, IPOD_LCD_BASE + LCD_DATA); + lcd_wait_write(); + outl(0x10, IPOD_LCD_BASE + LCD_DATA); #endif } @@ -185,6 +248,9 @@ (void)stride; } + + +#if (CONFIG_LCD == LCD_IPODNANO) || (CONFIG_LCD == LCD_IPODCOLOR) /* Update a fraction of the display. */ void lcd_update_rect(int x, int y, int width, int height) { @@ -293,6 +359,71 @@ height = height - h; } } +#elif CONFIG_LCD == LCD_IPOD2BPP +void lcd_update_rect(int x, int y, int width, int height) +{ + int cursor_pos, xx; + int ny, newx, newwidth; + int sx = x, sy = y, mx = width, my = height; + unsigned char *addr = (unsigned char *)lcd_framebuffer; + + newx=x&~1; + newwidth=width&~1; + if (newx+newwidth < x+width) { newwidth+=2; } + x=newx; width=newwidth; + /* only update the ipod if we are writing to the screen */ + mx = width; + sx = x; + + sx >>= 3; + //mx = (mx+7)>>3; + mx >>= 3; + + cursor_pos = sx + (sy << 5); + + for ( ny = sy; ny <= my; ny++ ) { + unsigned char * img_data; + + + // move the cursor + lcd_cmd_and_data(0x11, cursor_pos >> 8, cursor_pos & 0xff); + + // setup for printing + lcd_prepare_cmd(0x12); + + img_data = (unsigned char *)&lcd_framebuffer[ny][x]; + + // 160/8 -> 20 == loops 20 times + // make sure we loop at least once + for ( xx = sx; xx <= mx; xx++ ) { + // display a character + lcd_send_data(*(img_data+1), *img_data); + + img_data += 2; + } + + // update cursor pos counter + cursor_pos += 0x20; + } +} + +/** Switch on or off the backlight **/ +void lcd_enable (bool on){ + int lcd_state; + + lcd_state = inl(IPOD_LCD_BASE); + if (on){ + lcd_state = lcd_state | 0x2; + outl(lcd_state, IPOD_LCD_BASE); + lcd_cmd_and_data(0x7, 0x0, 0x11); + } + else { + lcd_state = lcd_state & ~0x2; + outl(lcd_state, IPOD_LCD_BASE); + lcd_cmd_and_data(0x7, 0x0, 0x9); + } +} +#endif /* Update the display. This must be called after all other LCD functions that change the display. */ Index: firmware/drivers/pcf50605.c =================================================================== RCS file: /cvsroot/rockbox/firmware/drivers/pcf50605.c,v retrieving revision 1.3 diff -u -r1.3 pcf50605.c --- firmware/drivers/pcf50605.c 21 Dec 2005 23:32:19 -0000 1.3 +++ firmware/drivers/pcf50605.c 22 Jan 2006 18:12:50 -0000 @@ -24,7 +24,11 @@ * ****************************************************************************/ #include "config.h" +#if CONFIG_I2C == I2C_PP5020 #include "i2c-pp5020.h" +#elif CONFIG_I2C == I2C_PP5002 +#include "i2c-pp5002.h" +#endif #include "rtc.h" #define OOCS 0x01 Index: firmware/drivers/power.c =================================================================== RCS file: /cvsroot/rockbox/firmware/drivers/power.c,v retrieving revision 1.64 diff -u -r1.64 power.c --- firmware/drivers/power.c 12 Jan 2006 00:35:50 -0000 1.64 +++ firmware/drivers/power.c 22 Jan 2006 18:12:50 -0000 @@ -175,8 +175,9 @@ and_l(~0x80000000, &GPIO_OUT); else or_l(0x80000000, &GPIO_OUT); -#elif CONFIG_CPU == PP5020 +#elif CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002 /* We do nothing on the iPod */ + #elif defined(GMINI_ARCH) if(on) P1 |= 0x08; @@ -232,6 +233,9 @@ #elif CONFIG_CPU == PP5020 /* pretend we are always powered - we don't turn it off on the ipod */ return true; +#elif CONFIG_CPU == PP5002 + /* pretend we are always powered - we don't turn it off on the ipod */ + return true; #elif defined(GMINI_ARCH) return (P1 & 0x08?true:false); #else /* SH1 based archos */ @@ -263,7 +267,7 @@ set_irq_level(HIGHEST_IRQ_LEVEL); #if CONFIG_CPU == MCF5249 and_l(~0x00080000, &GPIO1_OUT); -#elif CONFIG_CPU == PP5020 +#elif CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002 #ifndef BOOTLOADER /* We don't turn off the ipod, we put it in a deep sleep */ pcf50605_standby_mode(); Index: firmware/drivers/serial.c =================================================================== RCS file: /cvsroot/rockbox/firmware/drivers/serial.c,v retrieving revision 1.20 diff -u -r1.20 serial.c --- firmware/drivers/serial.c 12 Jan 2006 00:35:50 -0000 1.20 +++ firmware/drivers/serial.c 22 Jan 2006 18:12:50 -0000 @@ -27,7 +27,7 @@ #include "lcd.h" #include "serial.h" -#if (CONFIG_CPU != MCF5249) && (CONFIG_CPU != TCC730) && (CONFIG_CPU != PP5020) && (CONFIG_CPU != PNX0101) +#if (CONFIG_CPU != MCF5249) && (CONFIG_CPU != TCC730) && (CONFIG_CPU != PP5020) && (CONFIG_CPU != PNX0101) && (CONFIG_CPU != PP5002) /* FIX: this doesn't work on iRiver or Gmini or iPod yet */ /* iFP7xx has no remote */ Index: firmware/export/button.h =================================================================== RCS file: /cvsroot/rockbox/firmware/export/button.h,v retrieving revision 1.33 diff -u -r1.33 button.h --- firmware/export/button.h 12 Jan 2006 00:35:50 -0000 1.33 +++ firmware/export/button.h 22 Jan 2006 18:12:50 -0000 @@ -163,6 +163,18 @@ #define BUTTON_SCROLL_FWD 0x0010 #define BUTTON_SCROLL_BACK 0x0020 +#elif CONFIG_KEYPAD == IPOD_3G_PAD + +/* TODO: These codes should relate to the hardware */ + +#define BUTTON_MENU 0x0002 +#define BUTTON_PLAY 0x0004 +#define BUTTON_SELECT 0x0008 +#define BUTTON_SCROLL_FWD 0x0010 +#define BUTTON_SCROLL_BACK 0x0020 +#define BUTTON_HOLD 0x0100 + + #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD #define BUTTON_PLAY 0x0001 Index: firmware/export/config.h =================================================================== RCS file: /cvsroot/rockbox/firmware/export/config.h,v retrieving revision 1.52 diff -u -r1.52 config.h --- firmware/export/config.h 12 Jan 2006 00:35:50 -0000 1.52 +++ firmware/export/config.h 22 Jan 2006 18:12:50 -0000 @@ -44,15 +44,16 @@ #define PNX0101 101 /* CONFIG_KEYPAD */ -#define PLAYER_PAD 0 -#define RECORDER_PAD 1 -#define ONDIO_PAD 2 -#define IRIVER_H100_PAD 3 -#define GMINI100_PAD 4 -#define IRIVER_H300_PAD 5 -#define IAUDIO_X5_PAD 6 -#define IPOD_4G_PAD 7 -#define IRIVER_IFP7XX_PAD 8 +#define PLAYER_PAD 0 +#define RECORDER_PAD 1 +#define ONDIO_PAD 2 +#define IRIVER_H100_PAD 3 +#define GMINI100_PAD 4 +#define IRIVER_H300_PAD 5 +#define IAUDIO_X5_PAD 6 +#define IPOD_4G_PAD 7 +#define IPOD_3G_PAD 8 +#define IRIVER_IFP7XX_PAD 9 /* CONFIG_REMOTE_KEYPAD */ #define H100_REMOTE 1 @@ -77,7 +78,8 @@ #define LCD_IPODCOLOR 6 /* as used by iPod Color/Photo */ #define LCD_IPODNANO 7 /* as used by iPod Nano */ #define LCD_IPODVIDEO 8 /* as used by iPod Video */ -#define LCD_IFP7XX 9 /* as used by iRiver iFP 7xx/8xx */ +#define LCD_IPOD2BPP 9 /* as used by iPod 3g with dock */ +#define LCD_IFP7XX 10 /* as used by iRiver iFP 7xx/8xx */ /* LCD_PIXELFORMAT */ #define RGB565 565 @@ -91,8 +93,9 @@ #define BL_GMINI 4 /* Archos GMini */ #define BL_IPOD4G 5 /* Apple iPod 4G */ #define BL_IPODNANO 6 /* Apple iPod Nano and iPod Video*/ -#define BL_IRIVER_H300 7 /* IRiver PWM */ -#define BL_IRIVER_IFP7XX 8 /* IRiver GPIO */ +#define BL_IPOD3G 7 /* Apple iPod 3g with dock */ +#define BL_IRIVER_H300 8 /* IRiver PWM */ +#define BL_IRIVER_IFP7XX 9 /* IRiver GPIO */ /* CONFIG_I2C */ #define I2C_PLAYREC 0 /* Archos Player/Recorder style */ @@ -100,7 +103,8 @@ #define I2C_GMINI 2 /* Gmini style */ #define I2C_COLDFIRE 3 /* Coldfire style */ #define I2C_PP5020 4 /* PP5020 style */ -#define I2C_PNX0101 5 /* PNX0101 style */ +#define I2C_PP5002 5 /* PP5002 style */ +#define I2C_PNX0101 6 /* PNX0101 style */ /* CONFIG_LED */ #define LED_REAL 1 /* SW controlled LED (Archos recorders, player, Gmini) */ @@ -111,7 +115,7 @@ /* CONFIG_RTC */ #define RTC_M41ST84W 1 /* Archos Recorder */ -#define RTC_PCF50605 2 /* iPod 4G */ +#define RTC_PCF50605 2 /* iPod 4G && iPod 3G*/ #define RTC_PCF50606 3 /* iriver H300 */ /* else HW controlled LED (iRiver H1x0) */ @@ -147,6 +151,8 @@ #include "config-ipodnano.h" #elif defined(IPOD_VIDEO) #include "config-ipodvideo.h" +#elif defined(IPOD_3G) +#include "config-ipod3g.h" #elif defined(IRIVER_IFP7XX) #include "config-ifp7xx.h" #else @@ -166,7 +172,7 @@ #endif /* define for all cpus from ARM family */ -#if (CONFIG_CPU == PP5020) || (CONFIG_CPU == PNX0101) +#if (CONFIG_CPU == PP5002) ||(CONFIG_CPU == PP5020) || (CONFIG_CPU == PNX0101) #define CPU_ARM #endif @@ -179,6 +185,7 @@ (((CONFIG_CPU == SH7034) && !defined(PLUGIN)) || /* SH1 archos: core only */ \ (CONFIG_CPU == MCF5249) || /* Coldfire: core, plugins, codecs */ \ (CONFIG_CPU == PP5020) || /* iPod: core, plugins, codecs */ \ + (CONFIG_CPU == PP5002) || /* iPod: core, plugins, codecs */ \ (CONFIG_CPU == TCC730)) /* CalmRISC16: core, (plugins, codecs) */ #define ICODE_ATTR __attribute__ ((section(".icode"))) #define ICONST_ATTR __attribute__ ((section(".irodata"))) Index: firmware/export/cpu.h =================================================================== RCS file: /cvsroot/rockbox/firmware/export/cpu.h,v retrieving revision 1.6 diff -u -r1.6 cpu.h --- firmware/export/cpu.h 12 Jan 2006 00:35:50 -0000 1.6 +++ firmware/export/cpu.h 22 Jan 2006 18:12:50 -0000 @@ -33,6 +33,9 @@ #if CONFIG_CPU == PP5020 #include "pp5020.h" #endif +#if CONFIG_CPU == PP5002 +#include "pp5002.h" +#endif #if CONFIG_CPU == PNX0101 #include "pnx0101.h" #endif Index: firmware/export/lcd.h =================================================================== RCS file: /cvsroot/rockbox/firmware/export/lcd.h,v retrieving revision 1.48 diff -u -r1.48 lcd.h --- firmware/export/lcd.h 20 Dec 2005 23:15:27 -0000 1.48 +++ firmware/export/lcd.h 22 Jan 2006 18:12:50 -0000 @@ -187,7 +187,7 @@ extern fb_data lcd_framebuffer[LCD_HEIGHT][LCD_WIDTH]; #endif -#if CONFIG_BACKLIGHT==BL_IRIVER_H300 +#if (CONFIG_BACKLIGHT==BL_IRIVER_H300)|| (CONFIG_BACKLIGHT==BL_IPOD3G) extern void lcd_enable(bool on); #endif Index: firmware/export/system.h =================================================================== RCS file: /cvsroot/rockbox/firmware/export/system.h,v retrieving revision 1.47 diff -u -r1.47 system.h --- firmware/export/system.h 12 Jan 2006 00:35:50 -0000 1.47 +++ firmware/export/system.h 22 Jan 2006 18:12:50 -0000 @@ -43,6 +43,21 @@ } #endif +#if CONFIG_CPU==PP5002 +#define inl(p) (*(volatile unsigned long *) (p)) +#define outl(v,p) (*(volatile unsigned long *) (p) = (v)) +#define inb(a) (*(volatile unsigned char *) (a)) +#define outb(a,b) (*(volatile unsigned char *) (b) = (a)) +#define inw(a) (*(volatile unsigned short *) (a)) +#define outw(a,b) (*(volatile unsigned short *) (b) = (a)) +static inline void udelay(unsigned usecs) +{ + unsigned start = inl( PP5002_TIMER_VAL); + while ((inl(PP5002_TIMER_VAL) - start) < usecs); +} + +//#define HIGHEST_IRQ_LEVEL 1 +#endif #ifdef HAVE_ADJUSTABLE_CPU_FREQ #define FREQ cpu_frequency void set_cpu_frequency(long frequency); Index: tools/configure =================================================================== RCS file: /cvsroot/rockbox/tools/configure,v retrieving revision 1.158 diff -u -r1.158 configure --- tools/configure 12 Jan 2006 00:35:50 -0000 1.158 +++ tools/configure 22 Jan 2006 18:12:51 -0000 @@ -384,6 +384,7 @@ echo "full path to the source code directory here:" firmdir=`input` + rootdir=$firmdir fi ##################################################################### @@ -425,7 +426,8 @@ echo "13 - iPod Color/Photo" echo "14 - iPod Nano" echo "15 - iPod Video" - echo "16 - iriver iFP-790" + echo "16 - iPod 3G" + echo "17 - iriver iFP-790" getit=`input`; @@ -693,6 +695,23 @@ ;; 16) + archos="ipodcolor" + target="-DIPOD_3G" + memory=32 # always + arm7tdmicc + tool="$rootdir/tools/scramble -add=ipco" + output="rockbox.ipod" + appextra="recorder:gui" + archosrom="" + flash="" + plugins="yes" + codecs="libmad liba52 libffmpegFLAC libTremor libwavpack dumb libmusepack libalac libfaad libm4a" + # toolset is the tools within the tools directory that we build for + # this particular target. + toolset=$ipodbitmaptools + ;; + + 17) archos="ifp7xx" target="-DIRIVER_IFP7XX" memory=1 Index: firmware/drivers/i2c-pp5002.c =================================================================== RCS file: firmware/drivers/i2c-pp5002.c diff -N firmware/drivers/i2c-pp5002.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ firmware/drivers/i2c-pp5002.c 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,171 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: i2c-pp5002.c,v 1.4 2005/12/19 14:30:52 dave Exp $ + * + * PP5002 I2C driver + * + * Based on code from the ipodlinux project - http://ipodlinux.org/ + * Adapted for Rockbox in November 2005 + * + * Original file: linux/arch/armnommu/mach-ipod/hardware.c + * + * Copyright (c) 2003-2005 Bernard Leach (leachbj@bouncycastle.org) + * + * 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 "cpu.h" +#include "kernel.h" +#include "logf.h" +#include "system.h" +#include "i2c-pp5002.h" + +/* Local functions definitions */ + +#define IPOD_I2C_BASE 0xc0008000 +#define IPOD_I2C_CTRL (IPOD_I2C_BASE+0x00) +#define IPOD_I2C_ADDR (IPOD_I2C_BASE+0x04) +#define IPOD_I2C_DATA0 (IPOD_I2C_BASE+0x0c) +#define IPOD_I2C_DATA1 (IPOD_I2C_BASE+0x10) +#define IPOD_I2C_DATA2 (IPOD_I2C_BASE+0x14) +#define IPOD_I2C_DATA3 (IPOD_I2C_BASE+0x18) +#define IPOD_I2C_STATUS (IPOD_I2C_BASE+0x1c) + +/* IPOD_I2C_CTRL bit definitions */ +#define IPOD_I2C_SEND 0x80 + +/* IPOD_I2C_STATUS bit definitions */ +#define IPOD_I2C_BUSY (1<<6) + +#define POLL_TIMEOUT (HZ) + +static int ipod_i2c_wait_not_busy(void) +{ + unsigned long timeout; + timeout = current_tick + POLL_TIMEOUT; + while (TIME_BEFORE(current_tick, timeout)) { + if (!(inb(IPOD_I2C_STATUS) & IPOD_I2C_BUSY)) { + return 0; + } + yield(); + } + + return -1; +} + + +/* Public functions */ + +int ipod_i2c_read_byte(unsigned int addr, unsigned int *data) +{ + if (ipod_i2c_wait_not_busy() < 0) + { + return -1; + } + + /* clear top 15 bits, left shift 1, or in 0x1 for a read */ + outb(((addr << 17) >> 16) | 0x1, IPOD_I2C_ADDR); + + outb(inb(IPOD_I2C_CTRL) | 0x20, IPOD_I2C_CTRL); + + outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL); + + if (ipod_i2c_wait_not_busy() < 0) + { + return -1; + } + + if (data) + { + *data = inb(IPOD_I2C_DATA0); + } + + return 0; +} + +int ipod_i2c_send_bytes(unsigned int addr, unsigned int len, unsigned char *data) +{ + int data_addr; + unsigned int i; + + if (len < 1 || len > 4) + { + return -1; + } + + if (ipod_i2c_wait_not_busy() < 0) + { + return -2; + } + + /* clear top 15 bits, left shift 1 */ + outb((addr << 17) >> 16, IPOD_I2C_ADDR); + + outb(inb(IPOD_I2C_CTRL) & ~0x20, IPOD_I2C_CTRL); + + data_addr = IPOD_I2C_DATA0; + for ( i = 0; i < len; i++ ) + { + outb(*data++, data_addr); + data_addr += 4; + } + + outb((inb(IPOD_I2C_CTRL) & ~0x26) | ((len-1) << 1), IPOD_I2C_CTRL); + + outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL); + + return 0x0; +} + +int ipod_i2c_send_byte(unsigned int addr, int data0) +{ + unsigned char data[1]; + + data[0] = data0; + + return ipod_i2c_send_bytes(addr, 1, data); +} + + +int i2c_readbyte(unsigned int dev_addr, int addr) +{ + int data; + + ipod_i2c_send_byte(dev_addr, addr); + ipod_i2c_read_byte(dev_addr, &data); + + return data; +} + +int ipod_i2c_send(unsigned int addr, int data0, int data1) +{ + unsigned char data[2]; + + data[0] = data0; + data[1] = data1; + + return ipod_i2c_send_bytes(addr, 2, data); +} + +void i2c_init(void) +{ + /* From ipodlinux */ + + // ipod_i2c_base = 0xc0008000; + + outl(inl(0xcf005000) | 0x2, 0xcf005000); + + outl(inl(0xcf005030) | (1<<8), 0xcf005030); + outl(inl(0xcf005030) & ~(1<<8), 0xcf005030); + +} Index: firmware/drivers/lcd-ipod2bpp.c =================================================================== RCS file: firmware/drivers/lcd-ipod2bpp.c diff -N firmware/drivers/lcd-ipod2bpp.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ firmware/drivers/lcd-ipod2bpp.c 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,1099 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: lcd-ipodvideo.c,v 1.3 2005/12/21 23:47:43 dave Exp $ + * + * LCD driver for iPod Video + * + * Based on code from the ipodlinux project - http://ipodlinux.org/ + * Adapted for Rockbox in December 2005 + * + * Original file: linux/arch/armnommu/mach-ipod/fb.c + * + * Copyright (c) 2003-2005 Bernard Leach (leachbj@bouncycastle.org) + * + * 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 "config.h" + +#include "cpu.h" +#include "lcd.h" +#include "kernel.h" +#include "thread.h" +#include +#include +#include "file.h" +#include "debug.h" +#include "system.h" +#include "font.h" +#include "rbunicode.h" +#include "bidi.h" + +/*** definitions ***/ + +/* LCD command codes */ +#define LCD_CNTL_POWER_CONTROL 0x25 +#define LCD_CNTL_VOLTAGE_SELECT 0x2b +#define LCD_CNTL_LINE_INVERT_DRIVE 0x36 +#define LCD_CNTL_GRAY_SCALE_PATTERN 0x39 +#define LCD_CNTL_TEMP_GRADIENT_SELECT 0x4e +#define LCD_CNTL_OSC_FREQUENCY 0x5f +#define LCD_CNTL_ON_OFF 0xae +#define LCD_CNTL_OSC_ON_OFF 0xaa +#define LCD_CNTL_OFF_MODE 0xbe +#define LCD_CNTL_REVERSE 0xa6 +#define LCD_CNTL_ALL_LIGHTING 0xa4 +#define LCD_CNTL_COMMON_OUTPUT_STATUS 0xc4 +#define LCD_CNTL_COLUMN_ADDRESS_DIR 0xa0 +#define LCD_CNTL_NLINE_ON_OFF 0xe4 +#define LCD_CNTL_DISPLAY_MODE 0x66 +#define LCD_CNTL_DUTY_SET 0x6d +#define LCD_CNTL_ELECTRONIC_VOLUME 0x81 +#define LCD_CNTL_DATA_INPUT_DIR 0x84 +#define LCD_CNTL_DISPLAY_START_LINE 0x8a + +#define LCD_CNTL_PAGE 0xb1 +#define LCD_CNTL_COLUMN 0x13 +#define LCD_CNTL_DATA_WRITE 0x1d + +#define SCROLLABLE_LINES 26 + +/*** globals ***/ + +unsigned char lcd_framebuffer[LCD_HEIGHT/4][LCD_WIDTH] IBSS_ATTR; + +static const unsigned char dibits[16] ICONST_ATTR = { + 0x00, 0x03, 0x0C, 0x0F, 0x30, 0x33, 0x3C, 0x3F, + 0xC0, 0xC3, 0xCC, 0xCF, 0xF0, 0xF3, 0xFC, 0xFF +}; + +static unsigned fg_pattern IDATA_ATTR = 0xFF; /* initially black */ +static unsigned bg_pattern IDATA_ATTR = 0x00; /* initially white */ +static int drawmode = DRMODE_SOLID; +static int xmargin = 0; +static int ymargin = 0; +static int curfont = FONT_SYSFIXED; + +/* scrolling */ +static volatile int scrolling_lines=0; /* Bitpattern of which lines are scrolling */ +static void scroll_thread(void); +static long scroll_stack[DEFAULT_STACK_SIZE/sizeof(long)]; +static const char scroll_name[] = "scroll"; +static int scroll_ticks = 12; /* # of ticks between updates*/ +static int scroll_delay = HZ/2; /* ticks delay before start */ +static int scroll_step = 6; /* pixels per scroll step */ +static int bidir_limit = 50; /* percent */ +static struct scrollinfo scroll[SCROLLABLE_LINES]; + +static const char scroll_tick_table[16] = { + /* Hz values: + 1, 1.25, 1.55, 2, 2.5, 3.12, 4, 5, 6.25, 8.33, 10, 12.5, 16.7, 20, 25, 33 */ + 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3 +}; + +#define IPOD_LCD_BASE 0xc0001000 + +/*** hardware configuration ***/ + +int lcd_default_contrast(void) +{ + return 28; +} + + + +/* LCD init */ +#ifdef SIMULATOR + +void lcd_init(void) +{ + create_thread(scroll_thread, scroll_stack, + sizeof(scroll_stack), scroll_name); +} +#else + +void lcd_init(void) +{ + /** to do **/ +// lcd_init_device(); ?? +} + +/*** update functions ***/ +/* srccopy bitblt, opcode is currently ignored*/ + +#endif /* !SIMULATOR */ + +/*** parameter handling ***/ + +void lcd_set_drawmode(int mode) +{ + drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); +} + +int lcd_get_drawmode(void) +{ + return drawmode; +} + +void lcd_set_foreground(unsigned brightness) +{ + fg_pattern = 0x55 * (~brightness & 3); +} + +unsigned lcd_get_foreground(void) +{ + return ~fg_pattern & 3; +} + +void lcd_set_background(unsigned brightness) +{ + bg_pattern = 0x55 * (~brightness & 3); +} + +unsigned lcd_get_background(void) +{ + return ~bg_pattern & 3; +} + +void lcd_set_drawinfo(int mode, unsigned fg_brightness, unsigned bg_brightness) +{ + lcd_set_drawmode(mode); + lcd_set_foreground(fg_brightness); + lcd_set_background(bg_brightness); +} + +void lcd_setmargins(int x, int y) +{ + xmargin = x; + ymargin = y; +} + +int lcd_getxmargin(void) +{ + return xmargin; +} + +int lcd_getymargin(void) +{ + return ymargin; +} + +void lcd_setfont(int newfont) +{ + curfont = newfont; +} + +int lcd_getstringsize(const unsigned char *str, int *w, int *h) +{ + return font_getstringsize(str, w, h, curfont); +} + +/*** low-level drawing functions ***/ + +static void setpixel(int x, int y) +{ + unsigned char *data = &lcd_framebuffer[y>>2][x]; + unsigned mask = 3 << (2 * (y & 3)); + *data = (*data & ~mask) | (fg_pattern & mask); +} + +static void clearpixel(int x, int y) +{ + unsigned char *data = &lcd_framebuffer[y>>2][x]; + unsigned mask = 3 << (2 * (y & 3)); + *data = (*data & ~mask) | (bg_pattern & mask); +} + +static void flippixel(int x, int y) +{ + lcd_framebuffer[y>>2][x] ^= 3 << (2 * (y & 3)); +} + +static void nopixel(int x, int y) +{ + (void)x; + (void)y; +} + +lcd_pixelfunc_type* const lcd_pixelfuncs[8] = { + flippixel, nopixel, setpixel, setpixel, + nopixel, clearpixel, nopixel, clearpixel +}; + +/* 'mask' and 'bits' contain 2 bits per pixel */ +static void flipblock(unsigned char *address, unsigned mask, unsigned bits) + ICODE_ATTR; +static void flipblock(unsigned char *address, unsigned mask, unsigned bits) +{ + *address ^= bits & mask; +} + +static void bgblock(unsigned char *address, unsigned mask, unsigned bits) + ICODE_ATTR; +static void bgblock(unsigned char *address, unsigned mask, unsigned bits) +{ + mask &= ~bits; + *address = (*address & ~mask) | (bg_pattern & mask); +} + +static void fgblock(unsigned char *address, unsigned mask, unsigned bits) + ICODE_ATTR; +static void fgblock(unsigned char *address, unsigned mask, unsigned bits) +{ + mask &= bits; + *address = (*address & ~mask) | (fg_pattern & mask); +} + +static void solidblock(unsigned char *address, unsigned mask, unsigned bits) + ICODE_ATTR; +static void solidblock(unsigned char *address, unsigned mask, unsigned bits) +{ + *address = (*address & ~mask) | (bits & mask & fg_pattern) + | (~bits & mask & bg_pattern); +} + +static void flipinvblock(unsigned char *address, unsigned mask, unsigned bits) + ICODE_ATTR; +static void flipinvblock(unsigned char *address, unsigned mask, unsigned bits) +{ + *address ^= ~bits & mask; +} + +static void bginvblock(unsigned char *address, unsigned mask, unsigned bits) + ICODE_ATTR; +static void bginvblock(unsigned char *address, unsigned mask, unsigned bits) +{ + mask &= bits; + *address = (*address & ~mask) | (bg_pattern & mask); +} + +static void fginvblock(unsigned char *address, unsigned mask, unsigned bits) + ICODE_ATTR; +static void fginvblock(unsigned char *address, unsigned mask, unsigned bits) +{ + mask &= ~bits; + *address = (*address & ~mask) | (fg_pattern & mask); +} + +static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits) + ICODE_ATTR; +static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits) +{ + *address = (*address & ~mask) | (~bits & mask & fg_pattern) + | (bits & mask & bg_pattern); +} + +lcd_blockfunc_type* const lcd_blockfuncs[8] = { + flipblock, bgblock, fgblock, solidblock, + flipinvblock, bginvblock, fginvblock, solidinvblock +}; + +/*** drawing functions ***/ + +/* Clear the whole display */ +void lcd_clear_display(void) +{ + unsigned bits = (drawmode & DRMODE_INVERSEVID) ? fg_pattern : bg_pattern; + + memset(lcd_framebuffer, bits, sizeof lcd_framebuffer); + scrolling_lines = 0; +} + +/* Set a single pixel */ +void lcd_drawpixel(int x, int y) +{ + if (((unsigned)x < LCD_WIDTH) && ((unsigned)y < LCD_HEIGHT)) + lcd_pixelfuncs[drawmode](x, y); +} + +/* Draw a line */ +void lcd_drawline(int x1, int y1, int x2, int y2) +{ + int numpixels; + int i; + int deltax, deltay; + int d, dinc1, dinc2; + int x, xinc1, xinc2; + int y, yinc1, yinc2; + lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[drawmode]; + + deltax = abs(x2 - x1); + deltay = abs(y2 - y1); + xinc2 = 1; + yinc2 = 1; + + if (deltax >= deltay) + { + numpixels = deltax; + d = 2 * deltay - deltax; + dinc1 = deltay * 2; + dinc2 = (deltay - deltax) * 2; + xinc1 = 1; + yinc1 = 0; + } + else + { + numpixels = deltay; + d = 2 * deltax - deltay; + dinc1 = deltax * 2; + dinc2 = (deltax - deltay) * 2; + xinc1 = 0; + yinc1 = 1; + } + numpixels++; /* include endpoints */ + + if (x1 > x2) + { + xinc1 = -xinc1; + xinc2 = -xinc2; + } + + if (y1 > y2) + { + yinc1 = -yinc1; + yinc2 = -yinc2; + } + + x = x1; + y = y1; + + for (i = 0; i < numpixels; i++) + { + if (((unsigned)x < LCD_WIDTH) && ((unsigned)y < LCD_HEIGHT)) + pfunc(x, y); + + if (d < 0) + { + d += dinc1; + x += xinc1; + y += yinc1; + } + else + { + d += dinc2; + x += xinc2; + y += yinc2; + } + } +} + +/* Draw a horizontal line (optimised) */ +void lcd_hline(int x1, int x2, int y) +{ + int x; + unsigned char *dst, *dst_end; + unsigned mask; + lcd_blockfunc_type *bfunc; + + /* direction flip */ + if (x2 < x1) + { + x = x1; + x1 = x2; + x2 = x; + } + + /* nothing to draw? */ + if (((unsigned)y >= LCD_HEIGHT) || (x1 >= LCD_WIDTH) || (x2 < 0)) + return; + + /* clipping */ + if (x1 < 0) + x1 = 0; + if (x2 >= LCD_WIDTH) + x2 = LCD_WIDTH-1; + + bfunc = lcd_blockfuncs[drawmode]; + dst = &lcd_framebuffer[y>>2][x1]; + mask = 3 << (2 * (y & 3)); + + dst_end = dst + x2 - x1; + do + bfunc(dst++, mask, 0xFFu); + while (dst <= dst_end); +} + +/* Draw a vertical line (optimised) */ +void lcd_vline(int x, int y1, int y2) +{ + int ny; + unsigned char *dst; + unsigned mask, mask_bottom; + lcd_blockfunc_type *bfunc; + + /* direction flip */ + if (y2 < y1) + { + ny = y1; + y1 = y2; + y2 = ny; + } + + /* nothing to draw? */ + if (((unsigned)x >= LCD_WIDTH) || (y1 >= LCD_HEIGHT) || (y2 < 0)) + return; + + /* clipping */ + if (y1 < 0) + y1 = 0; + if (y2 >= LCD_HEIGHT) + y2 = LCD_HEIGHT-1; + + bfunc = lcd_blockfuncs[drawmode]; + dst = &lcd_framebuffer[y1>>2][x]; + ny = y2 - (y1 & ~3); + mask = 0xFFu << (2 * (y1 & 3)); + mask_bottom = 0xFFu >> (2 * (~ny & 3)); + + for (; ny >= 4; ny -= 4) + { + bfunc(dst, mask, 0xFFu); + dst += LCD_WIDTH; + mask = 0xFFu; + } + mask &= mask_bottom; + bfunc(dst, mask, 0xFFu); +} + +/* Draw a rectangular box */ +void lcd_drawrect(int x, int y, int width, int height) +{ + if ((width <= 0) || (height <= 0)) + return; + + int x2 = x + width - 1; + int y2 = y + height - 1; + + lcd_vline(x, y, y2); + lcd_vline(x2, y, y2); + lcd_hline(x, x2, y); + lcd_hline(x, x2, y2); +} + +/* Fill a rectangular area */ +void lcd_fillrect(int x, int y, int width, int height) +{ + int ny; + unsigned char *dst, *dst_end; + unsigned mask, mask_bottom; + unsigned bits = fg_pattern; + lcd_blockfunc_type *bfunc; + bool fillopt; + + /* nothing to draw? */ + if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) + || (x + width <= 0) || (y + height <= 0)) + return; + + /* clipping */ + if (x < 0) + { + width += x; + x = 0; + } + if (y < 0) + { + height += y; + y = 0; + } + if (x + width > LCD_WIDTH) + width = LCD_WIDTH - x; + if (y + height > LCD_HEIGHT) + height = LCD_HEIGHT - y; + + fillopt = (drawmode & DRMODE_INVERSEVID) ? + (drawmode & DRMODE_BG) : (drawmode & DRMODE_FG); + if (fillopt &&(drawmode & DRMODE_INVERSEVID)) + bits = bg_pattern; + bfunc = lcd_blockfuncs[drawmode]; + dst = &lcd_framebuffer[y>>2][x]; + ny = height - 1 + (y & 3); + mask = 0xFFu << (2 * (y & 3)); + mask_bottom = 0xFFu >> (2 * (~ny & 3)); + + for (; ny >= 4; ny -= 4) + { + if (fillopt && (mask == 0xFFu)) + memset(dst, bits, width); + else + { + unsigned char *dst_row = dst; + + dst_end = dst_row + width; + do + bfunc(dst_row++, mask, 0xFFu); + while (dst_row < dst_end); + } + + dst += LCD_WIDTH; + mask = 0xFFu; + } + mask &= mask_bottom; + + if (fillopt && (mask == 0xFFu)) + memset(dst, bits, width); + else + { + dst_end = dst + width; + do + bfunc(dst++, mask, 0xFFu); + while (dst < dst_end); + } +} + +/* About Rockbox' internal monochrome bitmap format: + * + * A bitmap contains one bit for every pixel that defines if that pixel is + * black (1) or white (0). Bits within a byte are arranged vertically, LSB + * at top. + * The bytes are stored in row-major order, with byte 0 being top left, + * byte 1 2nd from left etc. The first row of bytes defines pixel rows + * 0..7, the second row defines pixel row 8..15 etc. + * + * This is similar to the internal lcd hw format. */ + +/* Draw a partial monochrome bitmap */ +void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, + int stride, int x, int y, int width, int height) + ICODE_ATTR; +void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, + int stride, int x, int y, int width, int height) +{ + int shift, ny; + unsigned char *dst, *dst_end; + unsigned mask, mask_bottom; + lcd_blockfunc_type *bfunc; + + /* nothing to draw? */ + if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) + || (x + width <= 0) || (y + height <= 0)) + return; + + /* clipping */ + if (x < 0) + { + width += x; + src_x -= x; + x = 0; + } + if (y < 0) + { + height += y; + src_y -= y; + y = 0; + } + if (x + width > LCD_WIDTH) + width = LCD_WIDTH - x; + if (y + height > LCD_HEIGHT) + height = LCD_HEIGHT - y; + + src += stride * (src_y >> 3) + src_x; /* move starting point */ + src_y &= 7; + y -= src_y; + dst = &lcd_framebuffer[y>>2][x]; + shift = y & 3; + ny = height - 1 + shift + src_y; + + bfunc = lcd_blockfuncs[drawmode]; + mask = 0xFFu << (shift + src_y); + mask_bottom = 0xFFu >> (~ny & 7); + + if (shift == 0) + { + unsigned dmask1, dmask2, data; + + for (; ny >= 8; ny -= 8) + { + const unsigned char *src_row = src; + unsigned char *dst_row = dst + LCD_WIDTH; + + dmask1 = dibits[mask&0x0F]; + dmask2 = dibits[(mask>>4)&0x0F]; + dst_end = dst_row + width; + + if (dmask1 != 0) + { + do + { + data = *src_row++; + bfunc(dst_row - LCD_WIDTH, dmask1, dibits[data&0x0F]); + bfunc(dst_row++, dmask2, dibits[(data>>4)&0x0F]); + } + while (dst_row < dst_end); + } + else + { + do + bfunc(dst_row++, dmask2, dibits[((*src_row++)>>4)&0x0F]); + while (dst_row < dst_end); + } + src += stride; + dst += 2*LCD_WIDTH; + mask = 0xFFu; + } + mask &= mask_bottom; + dmask1 = dibits[mask&0x0F]; + dmask2 = dibits[(mask>>4)&0x0F]; + dst_end = dst + width; + + if (dmask1 != 0) + { + if (dmask2 != 0) + { + do + { + data = *src++; + bfunc(dst, dmask1, dibits[data&0x0F]); + bfunc((dst++) + LCD_WIDTH, dmask2, dibits[(data>>4)&0x0F]); + } + while (dst < dst_end); + } + else + { + do + bfunc(dst++, dmask1, dibits[(*src++)&0x0F]); + while (dst < dst_end); + } + } + else + { + do + bfunc((dst++) + LCD_WIDTH, dmask2, dibits[((*src++)>>4)&0x0F]); + while (dst < dst_end); + } + } + else + { + dst_end = dst + width; + do + { + const unsigned char *src_col = src++; + unsigned char *dst_col = dst++; + unsigned mask_col = mask; + unsigned data = 0; + + for (y = ny; y >= 8; y -= 8) + { + data |= *src_col << shift; + + if (mask_col & 0xFFu) + { + if (mask_col & 0x0F) + bfunc(dst_col, dibits[mask_col&0x0F], dibits[data&0x0F]); + bfunc(dst_col + LCD_WIDTH, dibits[(mask_col>>4)&0x0F], + dibits[(data>>4)&0x0F]); + mask_col = 0xFFu; + } + else + mask_col >>= 8; + + src_col += stride; + dst_col += 2*LCD_WIDTH; + data >>= 8; + } + data |= *src_col << shift; + mask_bottom &= mask_col; + if (mask_bottom & 0x0F) + bfunc(dst_col, dibits[mask_bottom&0x0F], dibits[data&0x0F]); + if (mask_bottom & 0xF0) + bfunc(dst_col + LCD_WIDTH, dibits[(mask_bottom&0xF0)>>4], + dibits[(data>>4)&0x0F]); + } + while (dst < dst_end); + } +} + +/* Draw a full monochrome bitmap */ +void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width, int height) +{ + lcd_mono_bitmap_part(src, 0, 0, width, x, y, width, height); +} + +/* About Rockbox' internal native bitmap format: + * + * A bitmap contains two bits for every pixel. 00 = white, 01 = light grey, + * 10 = dark grey, 11 = black. Bits within a byte are arranged vertically, LSB + * at top. + * The bytes are stored in row-major order, with byte 0 being top left, + * byte 1 2nd from left etc. The first row of bytes defines pixel rows + * 0..3, the second row defines pixel row 4..7 etc. + * + * This is the same as the internal lcd hw format. */ + +/* Draw a partial native bitmap */ +void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y, + int stride, int x, int y, int width, int height) + ICODE_ATTR; +void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y, + int stride, int x, int y, int width, int height) +{ + int shift, ny; + unsigned char *dst, *dst_end; + unsigned mask, mask_bottom; + lcd_blockfunc_type *bfunc; + + /* nothing to draw? */ + if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) + || (x + width <= 0) || (y + height <= 0)) + return; + + /* clipping */ + if (x < 0) + { + width += x; + src_x -= x; + x = 0; + } + if (y < 0) + { + height += y; + src_y -= y; + y = 0; + } + if (x + width > LCD_WIDTH) + width = LCD_WIDTH - x; + if (y + height > LCD_HEIGHT) + height = LCD_HEIGHT - y; + + src += stride * (src_y >> 2) + src_x; /* move starting point */ + src_y &= 3; + y -= src_y; + dst = &lcd_framebuffer[y>>2][x]; + shift = y & 3; + ny = height - 1 + shift + src_y; + + bfunc = lcd_blockfuncs[drawmode]; + mask = 0xFFu << (2 * (shift + src_y)); + mask_bottom = 0xFFu >> (2 * (~ny & 3)); + + if (shift == 0) + { + for (; ny >= 4; ny -= 4) + { + if (mask == 0xFFu) + memcpy(dst, src, width); + else + { + const unsigned char *src_row = src; + unsigned char *dst_row = dst; + + dst_end = dst_row + width; + do + bfunc(dst_row++, mask, *src_row++); + while (dst_row < dst_end); + } + + src += stride; + dst += LCD_WIDTH; + mask = 0xFFu; + } + mask &= mask_bottom; + + if (mask == 0xFFu) + memcpy(dst, src, width); + else + { + dst_end = dst + width; + do + bfunc(dst++, mask, *src++); + while (dst < dst_end); + } + } + else + { + shift *= 2; + dst_end = dst + width; + do + { + const unsigned char *src_col = src++; + unsigned char *dst_col = dst++; + unsigned mask_col = mask; + unsigned data = 0; + + for (y = ny; y >= 4; y -= 4) + { + data |= *src_col << shift; + + if (mask_col & 0xFFu) + { + bfunc(dst_col, mask_col, data); + mask_col = 0xFFu; + } + else + mask_col >>= 8; + + src_col += stride; + dst_col += LCD_WIDTH; + data >>= 8; + } + data |= *src_col << shift; + bfunc(dst_col, mask_col & mask_bottom, data); + } + while (dst < dst_end); + } +} + +/* Draw a full native bitmap */ +void lcd_bitmap(const unsigned char *src, int x, int y, int width, int height) +{ + lcd_bitmap_part(src, 0, 0, width, x, y, width, height); +} + +/* put a string at a given pixel position, skipping first ofs pixel columns */ +static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) +{ + unsigned short ch; + unsigned short *ucs; + struct font* pf = font_get(curfont); + + ucs = bidi_l2v(str, 1); + + while ((ch = *ucs++) != 0 && x < LCD_WIDTH) + { + int width; + const unsigned char *bits; + + /* check input range */ + if (ch < pf->firstchar || ch >= pf->firstchar+pf->size) + ch = pf->defaultchar; + ch -= pf->firstchar; + + /* get proportional width and glyph bits */ + width = font_get_width(pf,ch); + + if (ofs > width) + { + ofs -= width; + continue; + } + + bits = font_get_bits(pf, ch); + + lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height); + + x += width - ofs; + ofs = 0; + } +} + +/* put a string at a given pixel position */ +void lcd_putsxy(int x, int y, const unsigned char *str) +{ + lcd_putsxyofs(x, y, 0, str); +} + +/*** line oriented text output ***/ + +void lcd_puts_style(int x, int y, const unsigned char *str, int style) +{ + int xpos,ypos,w,h; + int lastmode = drawmode; + + /* make sure scrolling is turned off on the line we are updating */ + scrolling_lines &= ~(1 << y); + + if(!str || !str[0]) + return; + + lcd_getstringsize(str, &w, &h); + xpos = xmargin + x*w / utf8length((char *)str); + ypos = ymargin + y*h; + lcd_putsxy(xpos, ypos, str); + drawmode = (DRMODE_SOLID|DRMODE_INVERSEVID); + lcd_fillrect(xpos + w, ypos, LCD_WIDTH - (xpos + w), h); + if (style & STYLE_INVERT) + { + drawmode = DRMODE_COMPLEMENT; + lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, h); + } + drawmode = lastmode; +} + +/* put a string at a given char position */ +void lcd_puts(int x, int y, const unsigned char *str) +{ + lcd_puts_style(x, y, str, STYLE_DEFAULT); +} + +/*** scrolling ***/ + +/* Reverse the invert setting of the scrolling line (if any) at given char + position. Setting will go into affect next time line scrolls. */ +void lcd_invertscroll(int x, int y) +{ + struct scrollinfo* s; + + (void)x; + + s = &scroll[y]; + s->invert = !s->invert; +} + +void lcd_stop_scroll(void) +{ + scrolling_lines=0; +} + +void lcd_scroll_speed(int speed) +{ + scroll_ticks = scroll_tick_table[speed]; +} + +void lcd_scroll_step(int step) +{ + scroll_step = step; +} + +void lcd_scroll_delay(int ms) +{ + scroll_delay = ms / (HZ / 10); +} + +void lcd_bidir_scroll(int percent) +{ + bidir_limit = percent; +} + +void lcd_puts_scroll(int x, int y, const unsigned char *string) +{ + lcd_puts_scroll_style(x, y, string, STYLE_DEFAULT); +} + +void lcd_puts_scroll_style(int x, int y, const unsigned char *string, int style) +{ + struct scrollinfo* s; + int w, h; + + s = &scroll[y]; + + s->start_tick = current_tick + scroll_delay; + s->invert = false; + if (style & STYLE_INVERT) { + s->invert = true; + lcd_puts_style(x,y,string,STYLE_INVERT); + } + else + lcd_puts(x,y,string); + + lcd_getstringsize(string, &w, &h); + + if (LCD_WIDTH - x * 8 - xmargin < w) { + /* prepare scroll line */ + char *end; + + memset(s->line, 0, sizeof s->line); + strcpy(s->line, (char *)string); + + /* get width */ + s->width = lcd_getstringsize((unsigned char *)s->line, &w, &h); + + /* scroll bidirectional or forward only depending on the string + width */ + if ( bidir_limit ) { + s->bidir = s->width < (LCD_WIDTH - xmargin) * + (100 + bidir_limit) / 100; + } + else + s->bidir = false; + + if (!s->bidir) { /* add spaces if scrolling in the round */ + strcat(s->line, " "); + /* get new width incl. spaces */ + s->width = lcd_getstringsize((unsigned char *)s->line, &w, &h); + } + + end = strchr(s->line, '\0'); + strncpy(end, (char *)string, LCD_WIDTH/2); + + s->len = utf8length((char *)string); + s->offset = 0; + s->startx = x; + s->backward = false; + scrolling_lines |= (1<start_tick)) + continue; + + if (s->backward) + s->offset -= scroll_step; + else + s->offset += scroll_step; + + pf = font_get(curfont); + xpos = xmargin + s->startx * s->width / s->len; + ypos = ymargin + index * pf->height; + + if (s->bidir) { /* scroll bidirectional */ + if (s->offset <= 0) { + /* at beginning of line */ + s->offset = 0; + s->backward = false; + s->start_tick = current_tick + scroll_delay * 2; + } + if (s->offset >= s->width - (LCD_WIDTH - xpos)) { + /* at end of line */ + s->offset = s->width - (LCD_WIDTH - xpos); + s->backward = true; + s->start_tick = current_tick + scroll_delay * 2; + } + } + else { + /* scroll forward the whole time */ + if (s->offset >= s->width) + s->offset %= s->width; + } + + lastmode = drawmode; + drawmode = (DRMODE_SOLID|DRMODE_INVERSEVID); + lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, pf->height); + drawmode = DRMODE_SOLID; + lcd_putsxyofs(xpos, ypos, s->offset, (unsigned char *)s->line); + if (s->invert) + { + drawmode = DRMODE_COMPLEMENT; + lcd_fillrect(xpos, ypos, LCD_WIDTH - xpos, pf->height); + } + drawmode = lastmode; + lcd_update_rect(xpos, ypos, LCD_WIDTH - xpos, pf->height); + } + + sleep(scroll_ticks); + } +} + + + Index: firmware/drivers/wm8731l.c =================================================================== RCS file: firmware/drivers/wm8731l.c diff -N firmware/drivers/wm8731l.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ firmware/drivers/wm8731l.c 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,276 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: wm8975.c,v 1.3 2005/12/19 14:30:52 dave Exp $ + * + * Driver for WM8975 audio codec + * + * Based on code from the ipodlinux project - http://ipodlinux.org/ + * Adapted for Rockbox in December 2005 + * + * Original file: linux/arch/armnommu/mach-ipod/audio.c + * + * Copyright (c) 2003-2005 Bernard Leach (leachbj@bouncycastle.org) + * + * 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 "audio.h" + +#include "i2c-pp5002.h" +#include "wm8731l.h" +#include "pcf50605.h" + +void wm8731l_reset(void); + +#define IPOD_PCM_LEVEL 0x65 /* -6dB */ + +#define RESET (0x0f<<1) +#define PWRMGMT1 (0x19<<1) +#define PWRMGMT2 (0x1a<<1) +#define AINTFCE (0x07<<1) +#define LOUT1VOL (0x02<<1) +#define ROUT1VOL (0x03<<1) +#define LOUT2VOL (0x28<<1) +#define ROUT2VOL (0x29<<1) + + +int wm8731l_mute(int mute) +{ + + if (mute) + { + /* Set DACMU = 1 to soft-mute the audio DACs. */ + ipod_i2c_send(0x1a, 0xa, 0x8); + } else { + /* Set DACMU = 0 to soft-un-mute the audio DACs. */ + ipod_i2c_send(0x1a, 0xa, 0x0); + } + + return 0; +} +/** From ipodLinux **/ +static void codec_set_active(int active) +{ + /* set active to 0x0 or 0x1 */ + if (active) { + ipod_i2c_send(0x1a, 0x12, 0x01); + } else { + ipod_i2c_send(0x1a, 0x12, 0x00); + } +} + +/* + * Reset the I2S BIT.FORMAT I2S, 16bit, FIFO.FORMAT 32bit + */ +static void i2s_reset(void) +{ + /* PP500x */ + + /* I2S device reset */ + outl(inl(0xcf005030) | 0x80, 0xcf005030); + outl(inl(0xcf005030) & ~0x80, 0xcf005030); + + /* I2S controller enable */ + outl(inl(0xc0002500) | 0x1, 0xc0002500); + + /* BIT.FORMAT [11:10] = I2S (default) */ + /* BIT.SIZE [9:8] = 24bit */ + /* FIFO.FORMAT = 24 bit LSB */ + + /* reset DAC and ADC fifo */ + outl(inl(0xc000251c) | 0x30000, 0xc000251c); +} + +/* + * Initialise the WM8975 for playback via headphone and line out. + * Note, I'm using the WM8750 datasheet as its apparently close. + */ +int wm8731l_init(void) { + /* reset I2C */ + i2c_init(); + + /* PP500x */ + + /* device reset */ + outl(inl(0xcf005030) | 0x80, 0xcf005030); + outl(inl(0xcf005030) & ~0x80, 0xcf005030); + + /* device enable */ + outl(inl(0xcf005000) | 0x80, 0xcf005000); + + /* GPIO D06 enable for output */ + outl(inl(0xcf00000c) | 0x40, 0xcf00000c); + outl(inl(0xcf00001c) & ~0x40, 0xcf00001c); +/* bits 11,10 == 01 */ + outl(inl(0xcf004040) | 0x400, 0xcf004040); + outl(inl(0xcf004040) & ~0x800, 0xcf004040); + + outl(inl(0xcf004048) & ~0x1, 0xcf004048); + + outl(inl(0xcf000004) & ~0xf, 0xcf000004); + outl(inl(0xcf004044) & ~0xf, 0xcf004044); + + /* C03 = 0 */ + outl(inl(0xcf000008) | 0x8, 0xcf000008); + outl(inl(0xcf000018) | 0x8, 0xcf000018); + outl(inl(0xcf000028) & ~0x8, 0xcf000028); + + return 0; +} + +/* Silently enable / disable audio output */ +void wm8731l_enable_output(bool enable) +{ + if (enable) + { + /* reset the I2S controller into known state */ + i2s_reset(); + + ipod_i2c_send(0x1a, 0x1e, 0x0); /*Reset*/ + + codec_set_active(0x0); + + /* DACSEL=1 */ + /* BYPASS=1 */ + ipod_i2c_send(0x1a, 0x8, 0x18); + + + /* set power register to POWEROFF=0 on OUTPD=0, DACPD=0 */ + ipod_i2c_send(0x1a, 0xc, 0x67); + + /* BCLKINV=0(Dont invert BCLK) MS=1(Enable Master) LRSWAP=0 LRP=0 */ + /* IWL=00(16 bit) FORMAT=10(I2S format) */ + ipod_i2c_send(0x1a, 0xe, 0x42); + + codec_set_sample_rate(WM8731L_44100HZ); + + /* set the volume to -6dB */ + ipod_i2c_send(0x1a, 0x4, IPOD_PCM_LEVEL); + ipod_i2c_send(0x1a, 0x6 | 0x1, IPOD_PCM_LEVEL); + + /* ACTIVE=1 */ + codec_set_active(1); + + /* 5. Set DACMU = 0 to soft-un-mute the audio DACs. */ + ipod_i2c_send(0x1a, 0xa, 0x0); + + wm8731l_mute(0); + } else { + wm8731l_mute(1); + } +} + +int wm8731l_set_master_vol(int vol_l, int vol_r) +{ + /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */ + /* 1111111 == +6dB */ + /* 1111001 == 0dB */ + /* 0110000 == -73dB */ + /* 0101111 == mute (0x2f) */ + if (vol_l == vol_r) { + ipod_i2c_send(0x1a, 0x4 | 0x1, vol_l); + } else { + ipod_i2c_send(0x1a, 0x4, vol_l); + ipod_i2c_send(0x1a, 0x6, vol_r); + } + + return 0; +} + +int wm8975_set_mixer_vol(int channel1, int channel2) +{ + (void)channel1; + (void)channel2; + + return 0; +} + +void wm8731l_set_bass(int value) +{ + (void)value; +} + +void wm8731l_set_treble(int value) +{ + (void)value; +} + + + +/* Nice shutdown of WM8975 codec */ +void wm8731l_close(void) +{ + /* set DACMU=1 DEEMPH=0 */ + ipod_i2c_send(0x1a, 0xa, 0x8); + + /* ACTIVE=0 */ + codec_set_active(0x0); + + /* line in mute left & right*/ + ipod_i2c_send(0x1a, 0x0 | 0x1, 0x80); + + /* set DACSEL=0, MUTEMIC=1 */ + ipod_i2c_send(0x1a, 0x8, 0x2); + + /* set POWEROFF=0 OUTPD=0 DACPD=1 */ + ipod_i2c_send(0x1a, 0xc, 0x6f); + + /* set POWEROFF=1 OUTPD=1 DACPD=1 */ + ipod_i2c_send(0x1a, 0xc, 0xff); +} + +/* Change the order of the noise shaper, 5th order is recommended above 32kHz */ +void wm8731l_set_nsorder(int order) +{ + (void)order; +} + +/* */ +void wm8731l_set_sample_rate(int sampling_control) { + codec_set_active(0x0); + ipod_i2c_send(0x1a, 0x10, sampling_control); + codec_set_active(0x1); + +} + +void wm8731l_enable_recording(bool source_mic) { + + (void)source_mic; +} + +void wm8731l_disable_recording(void) { + +} + +void wm8731l_set_recvol(int left, int right, int type) { + + (void)left; + (void)right; + (void)type; +} + +void wm8731l_set_monitor(int enable) { + + (void)enable; +} Index: firmware/export/config-ipod3g.h =================================================================== RCS file: firmware/export/config-ipod3g.h diff -N firmware/export/config-ipod3g.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ firmware/export/config-ipod3g.h 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,99 @@ +/* + * This config file is for the Apple iPod 3g + */ +#define APPLE_IPOD3G 1 + +/* For Rolo and boot loader */ +#define MODEL_NUMBER 1 + +/* define this if you have recording possibility */ +/*#define HAVE_RECORDING 1*/ + +/* define this if you have a bitmap LCD display */ +#define HAVE_LCD_BITMAP 1 + +/* define this if you have a colour LCD */ +#define HAVE_LCD_COLOR 0 + +/* LCD dimensions */ +#define LCD_WIDTH 128 +#define LCD_HEIGHT 160 +#define LCD_DEPTH 2 /* 3 colours */ +//#define LCD_PIXELFORMAT RGB565SWAPPED /* rgb565 byte-swapped */ + +#define CONFIG_KEYPAD IPOD_3G_PAD + +/* Define this if you do software codec */ +#define CONFIG_CODEC SWCODEC + +/* define this if you have a real-time clock */ +#ifndef BOOTLOADER +#define CONFIG_RTC RTC_PCF50605 +#endif + +/* Define this if you have a software controlled poweroff */ +#define HAVE_SW_POWEROFF + +/* The number of bytes reserved for loadable codecs */ +#define CODEC_SIZE 0x80000 + +/* The number of bytes reserved for loadable plugins */ +#define PLUGIN_BUFFER_SIZE 0xC0000 + +/* Define this if you have the WM8731L audio codec */ +#define HAVE_WM8731L + +/* Define this for LCD backlight available */ +#define CONFIG_BACKLIGHT BL_IPOD3G /* port controlled */ + +#ifndef SIMULATOR + +/* Define this if you have a PortalPlayer PP5002 */ +#define CONFIG_CPU PP5002 + +/* Define this if you want to use the PP5002 i2c interface */ +#define CONFIG_I2C I2C_PP5002 + +/* Type of mobile power */ +//#define CONFIG_BATTERY BATT_LIPOL1300 + +#define BATTERY_SCALE_FACTOR 16665 /* FIX: this value is picked at random */ + +/* Define this if the platform can charge batteries */ +//#define HAVE_CHARGING 1 + +/* define this if the hardware can be powered off while charging */ +//#define HAVE_POWEROFF_WHILE_CHARGING + +/* The start address index for ROM builds */ +#define ROM_START 0x00000000 + +/* Define this to the CPU frequency */ +#define CPU_FREQ 11289600 + +#define CONFIG_LCD LCD_IPOD2BPP + +/* Offset ( in the firmware file's header ) to the file length */ +#define FIRMWARE_OFFSET_FILE_LENGTH 0 + +/* Offset ( in the firmware file's header ) to the file CRC */ +#define FIRMWARE_OFFSET_FILE_CRC 0 + +/* Offset ( in the firmware file's header ) to the real data */ +#define FIRMWARE_OFFSET_FILE_DATA 8 + +#define USB_IPODSTYLE + +/* define this if the unit can be powered or charged via USB */ +#define HAVE_USB_POWER + +/* Virtual LED (icon) */ +#define CONFIG_LED LED_VIRTUAL + +/* Define this if you have adjustable CPU frequency */ +//#define HAVE_ADJUSTABLE_CPU_FREQ + +#define BOOTFILE_EXT "ipod" +#define BOOTFILE "rockbox." BOOTFILE_EXT + +#endif Index: firmware/export/i2c-pp5002.h =================================================================== RCS file: firmware/export/i2c-pp5002.h diff -N firmware/export/i2c-pp5002.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ firmware/export/i2c-pp5002.h 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,34 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: i2c-pp5002.h,v 1.3 2005/12/11 10:52:17 dave Exp $ + * + * Copyright (C) 2002 by Linus Nielsen Feltzing + * + * 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. + * + ****************************************************************************/ + +/* + * PP5002 i2c driver + * + */ + +#ifndef _I2C_PP5002_H +#define _I2C_PP5002_H + +/* TODO: Fully implement i2c driver */ + +void i2c_init(void); +int i2c_readbyte(unsigned int dev_addr, int addr); +int ipod_i2c_send(unsigned int addr, int data0, int data1); + +#endif Index: firmware/export/pp5002.h =================================================================== RCS file: firmware/export/pp5002.h diff -N firmware/export/pp5002.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ firmware/export/pp5002.h 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,103 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: pp5020.h,v 1.3 2006/01/07 00:43:48 dave Exp $ + * + * Copyright (C) 2004 by Thom Johansen + * + * 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. + * + ****************************************************************************/ +#ifndef __PP5020_H__ +#define __PP5020_H__ + +/* All info gleaned and/or copied from the iPodLinux project. */ + +#define GPIOA_ENABLE (*(volatile unsigned long *)( 0xcf000000)) +#define GPIOB_ENABLE (*(volatile unsigned long *)(0xcf000004)) +#define GPIOC_ENABLE (*(volatile unsigned long *)(0xcf000008)) +#define GPIOD_ENABLE (*(volatile unsigned long *)(0xcf00000c)) +#define GPIOA_OUTPUT_EN (*(volatile unsigned long *)(0xcf000010)) +#define GPIOB_OUTPUT_EN (*(volatile unsigned long *)(0xcf000014)) +#define GPIOC_OUTPUT_EN (*(volatile unsigned long *)(0xcf000018)) +#define GPIOD_OUTPUT_EN (*(volatile unsigned long *)(0xcf00001c)) +#define GPIOA_OUTPUT_VAL (*(volatile unsigned long *)(0xcf000020)) +#define GPIOB_OUTPUT_VAL (*(volatile unsigned long *)(0xcf000024)) +#define GPIOC_OUTPUT_VAL (*(volatile unsigned long *)(0xcf000028)) +#define GPIOD_OUTPUT_VAL (*(volatile unsigned long *)(0xcf00002c)) +#define GPIOA_INPUT_VAL (*(volatile unsigned long *)(0xcf000030)) +#define GPIOB_INPUT_VAL (*(volatile unsigned long *)(0xcf000034)) +#define GPIOC_INPUT_VAL (*(volatile unsigned long *)(0xcf000038)) +#define GPIOD_INPUT_VAL (*(volatile unsigned long *)(0xcf00003c)) +#define GPIOA_INT_STAT (*(volatile unsigned long *)(0xcf000040)) +#define GPIOB_INT_STAT (*(volatile unsigned long *)(0xcf000044)) +#define GPIOC_INT_STAT (*(volatile unsigned long *)(0xcf000048)) +#define GPIOD_INT_STAT (*(volatile unsigned long *)(0xcf00004c)) +#define GPIOA_INT_EN (*(volatile unsigned long *)(0xcf000050)) +#define GPIOB_INT_EN (*(volatile unsigned long *)(0xcf000054)) +#define GPIOC_INT_EN (*(volatile unsigned long *)(0xcf000058)) +#define GPIOD_INT_EN (*(volatile unsigned long *)(0xcf00005c)) +#define GPIOA_INT_LEV (*(volatile unsigned long *)(0xcf000060)) +#define GPIOB_INT_LEV (*(volatile unsigned long *)(0xcf000064)) +#define GPIOC_INT_LEV (*(volatile unsigned long *)(0xcf000068)) +#define GPIOD_INT_LEV (*(volatile unsigned long *)(0xcf00006c)) +#define GPIOA_INT_CLR (*(volatile unsigned long *)(0xcf000070)) +#define GPIOB_INT_CLR (*(volatile unsigned long *)(0xcf000074)) +#define GPIOC_INT_CLR (*(volatile unsigned long *)(0xcf000078)) +#define GPIOD_INT_CLR (*(volatile unsigned long *)(0xcf00007c)) +/* +#define DEV_RS (*(volatile unsigned long *)(0x60006004)) +#define DEV_EN (*(volatile unsigned long *)(0x6000600c)) + + +#define PP5020_CPU_INT_STAT (*(volatile unsigned long*)(0x64004000)) +#define PP5020_CPU_HI_INT_STAT (*(volatile unsigned long*)(0x64004100)) +#define PP5020_CPU_INT_EN (*(volatile unsigned long*)(0x60004024)) +#define PP5020_CPU_HI_INT_EN (*(volatile unsigned long*)(0x60004124)) +#define PP5020_CPU_INT_CLR (*(volatile unsigned long*)(0x60004028)) +#define PP5020_CPU_HI_INT_CLR (*(volatile unsigned long*)(0x60004128)) + + +*/ +#define USB2D_IDENT (*(volatile unsigned long*)(0xc5000000)) +#define USB_STATUS (*(volatile unsigned long*)(0xc50001a4)) +#define USECS_PER_INT 0x2710 + +/* PP5002 registers */ +#define PP5002_TIMER1 0xcf001100 +#define PP5002_TIMER1_ACK 0xcf001104 +#define PP5002_TIMER2 0xcf001108 +#define PP5002_TIMER2_ACK 0xcf00110c + +#define PP5002_TIMER_STATUS 0xcf001110 + +#define PP5002_IDE_IRQ 1 +#define PP5002_SER0_IRQ 4 +#define PP5002_I2S_IRQ 5 +#define PP5002_SER1_IRQ 7 +#define PP5002_TIMER1_IRQ 11 +#define PP5002_GPIO_IRQ 14 +#define PP5002_DMA_OUT_IRQ 30 +#define PP5002_DMA_IN_IRQ 31 + +#define PP5002_VALID_IRQ(x) (x==PP5002_IDE_IRQ||x==PP5002_SER0_IRQ||x==PP5002_I2S_IRQ||x==PP5002_SER1_IRQ||x==PP5002_TIMER1_IRQ||x==PP5002_GPIO_IRQ||x==PP5002_DMA_OUT_IRQ||x==PP5002_DMA_IN_IRQ) + +#define PP5002_IDE_MASK (1 << PP5002_IDE_IRQ) +#define PP5002_SER0_MASK (1 << PP5002_SER0_IRQ) +#define PP5002_I2S_MASK (1 << PP5002_I2S_IRQ) +#define PP5002_SER1_MASK (1 << PP5002_SER1_IRQ) +#define PP5002_TIMER1_MASK (1 << PP5002_TIMER1_IRQ) +#define PP5002_GPIO_MASK (1 << PP5002_GPIO_IRQ) +#define PP5002_DMA_OUT_MASK (1 << PP5002_DMA_OUT_IRQ) + + +#define PP5002_TIMER_VAL 0xcf001110 +#endif Index: firmware/export/wm8731l.h =================================================================== RCS file: firmware/export/wm8731l.h diff -N firmware/export/wm8731l.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ firmware/export/wm8731l.h 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,54 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: wm8975.h,v 1.3 2005/12/19 14:38:59 dave Exp $ + * + * Copyright (C) 2005 by Dave Chapman + * + * 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. + * + ****************************************************************************/ + +#ifndef _WM8731L_H +#define _WM8731L_H + +extern void wm8731l_reset(void); +extern int wm8731l_init(void); +extern void wm8731l_enable_output(bool enable); +extern int wm8731l_set_master_vol(int vol_l, int vol_r); +extern int wm8731l_set_mixer_vol(int channel1, int channel2); +extern void wm8731l_set_bass(int value); +extern void wm8731l_set_treble(int value); +extern int wm8731l_mute(int mute); +extern void wm8731l_close(void); +extern void wm8731l_set_nsorder(int order); +extern void wm8731l_set_sample_rate(int sampling_control); + +extern void wm8731l_enable_recording(bool source_mic); +extern void wm8731l_disable_recording(void); +extern void wm8731l_set_recvol(int left, int right, int type); +extern void wm8731l_set_monitor(int enable); + +/* Register settings for the supported samplerates: */ +#define WM8731L_8000HZ 0x4d +/* + IpodLinux don't seem to support those sampling rate with the wm8731L chip +#define WM8975_16000HZ 0x55 +#define WM8975_22050HZ 0x77 +#define WM8975_24000HZ 0x79 +*/ +#define WM8731L_32000HZ 0x59 +#define WM8731L_44100HZ 0x63 +#define WM8731L_48000HZ 0x41 +#define WM8731L_88200HZ 0x7f +#define WM8731L_96000HZ 0x5d + +#endif /* _WM8975_H */