merge a big part of the unofficial gigabeat cvs back. Includes working bootloader and rockbox with audio.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11850 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Marcoen Hirschberg 2006-12-29 02:49:12 +00:00
parent 995a804def
commit 295367686e
31 changed files with 1506 additions and 196 deletions

View file

@ -36,6 +36,11 @@ OUTPUT_FORMAT(elf32-sh)
#define DRAMORIG 0xc00000 + STUBOFFSET #define DRAMORIG 0xc00000 + STUBOFFSET
#define IRAMORIG 0x407000 #define IRAMORIG 0x407000
#define IRAMSIZE 0x9000 #define IRAMSIZE 0x9000
#elif CONFIG_CPU == S3C2440
#define DRAMORIG 0x100 + STUBOFFSET
#define IRAMORIG DRAMORIG
#define IRAMSIZE 4K
#define IRAM DRAM
#else #else
#define DRAMORIG 0x09000000 + STUBOFFSET #define DRAMORIG 0x09000000 + STUBOFFSET
#endif #endif
@ -73,7 +78,7 @@ SECTIONS
.text : .text :
{ {
*(.text*) *(.text*)
#if defined(CPU_PP) || (CONFIG_CPU==PNX0101) #ifdef CPU_ARM
*(.glue_7) *(.glue_7)
*(.glue_7t) *(.glue_7t)
#endif #endif

View file

@ -17,12 +17,133 @@
#include "panic.h" #include "panic.h"
#include "power.h" #include "power.h"
#include "file.h" #include "file.h"
#include "button-target.h"
void map_memory(void);
int line = 0;
char version[] = APPSVERSION; char version[] = APPSVERSION;
void go_usb_mode(void) { /* This section allows you to toggle bits of any memory location */
/* Touchpad to move around the bits. Select to toggle the red bit */
typedef struct {
unsigned int address;
char *desc;
} memlocation_struct;
/* Just add any address and descriptions here */
/* Must finish with 0xFFFFFFFF */
const memlocation_struct memlocations[] = {
/* Address Description */
{ 0x56000000, "GPACON" },
{ 0x56000004, "GPADAT" },
{ 0x56000010, "GPBCON" },
{ 0x56000014, "GPBDAT" },
{ 0x56000020, "GPCCON" },
{ 0x56000024, "GPCDAT" },
{ 0x56000030, "GPDCON" },
{ 0x56000034, "GPDDAT" },
{ 0x56000040, "GPECON" },
{ 0x56000044, "GPEDAT" },
{ 0x56000050, "GPFCON" },
{ 0x56000054, "GPFDAT" },
{ 0x56000060, "GPGCON" },
{ 0x56000064, "GPGDAT" },
{ 0x56000070, "GPHCON" },
{ 0x56000074, "GPHDAT" },
{ 0xFFFFFFFF, 0 }
};
void memdump(void)
{
int i, j;
int current=0, bit=0;
char * bitval;
int data;
char tmp[40];
while(1) {
i = 0;
while(memlocations[i].address != 0xFFFFFFFF) {
data = *(volatile int *)memlocations[i].address;
snprintf(tmp, sizeof(tmp), "%s %s 0x%08X",
(i==current) ? "*" : " ",
memlocations[i].desc,
data);
lcd_puts(0, i*2+5, tmp);
/* print out in binary, current bit in red */
for (j=31; j>=0; j--) {
if ((bit == j) && (current == i))
lcd_set_foreground(LCD_RGBPACK(255,0,0));
lcd_puts((31-j) + ((31-j) / 8), i*2+6, (data & (1 << j)) ? "1" : "0" );
lcd_set_foreground(LCD_RGBPACK(0,0,0));
}
i++;
}
data = *(volatile int *)memlocations[current].address;
bitval = (data & (1 << bit)) ? "1" : "0";
snprintf(tmp, sizeof(tmp), "%s bit %ld = %s", memlocations[current].desc, bit, bitval);
lcd_puts(0, (i*2)+7, tmp);
lcd_update();
/* touchpad controls */
/* Up */
if (GPJDAT & 0x01) {
if (current > 0)
current--;
while(GPJDAT & 0x01);
}
/* Down */
if (GPJDAT & 0x40) {
if (current < (i-1))
current++;
while(GPJDAT & 0x40);
}
/* Left */
if (GPJDAT & 0x80) {
if (bit < 31)
bit++;
while(GPJDAT & 0x80);
}
/* Right */
if (GPJDAT & 0x1000) {
if (bit > 0)
bit--;
while(GPJDAT & 0x1000);
}
/* Centre - Toggle Bit */
if (GPJDAT & 0x08) {
data = *(volatile int *)memlocations[current].address;
data = data ^ (1 << bit);
*(volatile int *)memlocations[current].address = data;
while(GPJDAT & 0x08);
}
/* Bail out if the power button is pressed */
if (GPGDAT & 1) {
break;
}
}
}
static void go_usb_mode(void) {
/* Drop into USB mode. This does not check for disconnection. */ /* Drop into USB mode. This does not check for disconnection. */
int i; int i;
GPBDAT &= 0x7EF; GPBDAT &= 0x7EF;
@ -38,13 +159,156 @@ void go_usb_mode(void) {
GPBDAT |= 1<<6; GPBDAT |= 1<<6;
} }
/* Restores a factory kernel/bootloader from a known location */
/* Restores the FWIMG01.DAT file back in the case of a bootloader failure */
/* The factory or "good" bootloader must be in /GBSYSTEM/FWIMG/FWIMG01.DAT.ORIG */
/* Returns non-zero on failure */
int restore_fwimg01dat(void)
{
int orig_file = 0, dest_file = 0;
int size = 0, size_read;
char buf[256];
char lcd_buf[64];
orig_file = open("/GBSYSTEM/FWIMG/FWIMG01.DAT.ORIG", O_RDONLY);
if (orig_file < 0) {
/* Couldn't open source file */
lcd_puts(0, line++, "Couldn't open FWIMG01.DAT.ORIG for reading");
lcd_update();
return(1);
}
lcd_puts(0, line++, "FWIMG01.DAT.ORIG opened for reading");
lcd_update();
dest_file = open("/GBSYSTEM/FWIMG/FWIMG01.DAT", O_RDWR);
if (dest_file < 0) {
/* Couldn't open destination file */
lcd_puts(0, line++, "Couldn't open FWIMG01.DAT.ORIG for writing");
lcd_update();
close(orig_file);
return(2);
}
lcd_puts(0, line++, "FWIMG01.DAT opened for writing");
lcd_update();
do {
/* Copy in chunks */
size_read = read(orig_file, buf, sizeof(buf));
if (size_read != write(dest_file, buf, size_read)) {
close(orig_file);
close(dest_file);
return(3);
}
size += size_read;
} while (size_read > 0);
close(orig_file);
close(dest_file);
snprintf(lcd_buf, sizeof(lcd_buf), "Finished copying %ld bytes from", size);
lcd_puts(0, line++, lcd_buf);
lcd_puts(0, line++, "FWIMG01.DAT.ORIG to FWIMG01.DAT");
return(0);
}
int load_rockbox(const char* file_name, unsigned char* buf, int buffer_size)
{
int fd;
int rc;
int len;
char str[256];
//unsigned long chksum;
//char model[5];
//unsigned long sum;
//int i;
//char str[80];
fd = open("/.rockbox/" BOOTFILE, O_RDONLY);
if(fd < 0)
{
fd = open("/" BOOTFILE, O_RDONLY);
if(fd < 0)
return -1;
}
fd = open(file_name, O_RDONLY);
if(fd < 0)
return -2;
len = filesize(fd);
if (len > buffer_size) {
snprintf(str, sizeof(str), "len: %d buf: %d", len, buffer_size);
lcd_puts(0, line++, str);
lcd_update();
return -6;
}
/*lseek(fd, FIRMWARE_OFFSET_FILE_CRC, SEEK_SET);
rc = read(fd, &chksum, 4);
chksum=betoh32(chksum);*/ /* Rockbox checksums are big-endian */
/*if(rc < 4)
return -2;
rc = read(fd, model, 4);
if(rc < 4)
return -3;
model[4] = 0;
snprintf(str, 80, "Model: %s", model);
lcd_puts(0, line++, str);
snprintf(str, 80, "Checksum: %x", chksum);
lcd_puts(0, line++, str);
lcd_update();
lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET);
*/
rc = read(fd, buf, len);
if(rc < len) {
snprintf(str, sizeof(str), "len: %d rc: %d", len, rc);
lcd_puts(0, line++, str);
lcd_update();
return -4;
}
close(fd);
/*sum = MODEL_NUMBER;
for(i = 0;i < len;i++) {
sum += buf[i];
}
snprintf(str, 80, "Sum: %x", sum);
lcd_puts(0, line++, str);
lcd_update();
if(sum != chksum)
return -5;*/
return len;
}
void * main(void) void * main(void)
{ {
int line = 0, i; int i;
char buf[256]; char buf[256];
struct partinfo* pinfo; struct partinfo* pinfo;
unsigned short* identify_info; unsigned short* identify_info;
int testfile; //int testfile;
unsigned char* loadbuffer;
int buffer_size;
bool load_original = false;
int rc;
int(*kernel_entry)(void);
lcd_init(); lcd_init();
lcd_setfont(FONT_SYSFIXED); lcd_setfont(FONT_SYSFIXED);
@ -57,7 +321,10 @@ void * main(void)
*/ */
lcd_puts(0, line++, "Hold MENU when booting for rescue mode."); lcd_puts(0, line++, "Hold MENU when booting for rescue mode.");
lcd_puts(0, line++, " \"VOL+\" button to restore original kernel");
lcd_puts(0, line++, " \"A\" button to load original firmware");
lcd_update(); lcd_update();
sleep(1*HZ);
/* hold MENU to enter rescue mode */ /* hold MENU to enter rescue mode */
if (GPGDAT & 2) { if (GPGDAT & 2) {
@ -67,12 +334,44 @@ void * main(void)
while(1); while(1);
} }
sleep(5*HZ);
if(GPGDAT & 0x10) {
load_original = true;
lcd_puts(0, line++, "Loading original firmware...");
lcd_update();
}
i = ata_init(); i = ata_init();
i = disk_mount_all(); i = disk_mount_all();
snprintf(buf, sizeof(buf), "disk_mount_all: %d", i); snprintf(buf, sizeof(buf), "disk_mount_all: %d", i);
lcd_puts(0, line++, buf); lcd_puts(0, line++, buf);
/* hold VOL+ to enter rescue mode to copy old image */
/* needs to be after ata_init and disk_mount_all */
if (GPGDAT & 4) {
/* Try to restore the original kernel/bootloader if a copy is found */
lcd_puts(0, line++, "Restoring FWIMG01.DAT...");
lcd_update();
if (!restore_fwimg01dat()) {
lcd_puts(0, line++, "Restoring FWIMG01.DAT successful.");
} else {
lcd_puts(0, line++, "Restoring FWIMG01.DAT failed.");
}
lcd_puts(0, line++, "Now power cycle to boot original");
lcd_update();
while(1);
}
/* Memory dump mode if Vol- pressed */
if (GPGDAT & 8) {
memdump();
}
identify_info = ata_get_identify(); identify_info = ata_get_identify();
for (i=0; i < 20; i++) for (i=0; i < 20; i++)
@ -99,13 +398,65 @@ void * main(void)
snprintf(buf, sizeof(buf), "Partition 0: 0x%02x %ld MB", snprintf(buf, sizeof(buf), "Partition 0: 0x%02x %ld MB",
pinfo->type, pinfo->size / 2048); pinfo->type, pinfo->size / 2048);
lcd_puts(0, line++, buf); lcd_puts(0, line++, buf);
testfile = open("/boottest.txt", O_WRONLY|O_CREAT|O_TRUNC);
write(testfile, "It works!", 9);
close(testfile);
lcd_update(); lcd_update();
/* Load original firmware */
if(load_original) {
loadbuffer = (unsigned char*)0x30008000;
buffer_size =(unsigned char*)0x31000000 - loadbuffer;
rc = load_rockbox("/rockbox.gigabeat", loadbuffer, buffer_size);
if (rc < 0) {
lcd_puts(0, line++, "failed to load original firmware. Loading rockbox");
lcd_update();
sleep(2*HZ);
goto load_rockbox;
}
snprintf(buf, sizeof(buf), "Loaded: %d", rc);
lcd_puts(0, line++, buf);
lcd_update();
sleep(2*HZ);
(*((int*)0x7000000)) = 333;
rc = *((int*)0x7000000+0x8000000);
snprintf(buf, sizeof(buf), "Bank0 mem test: %d", rc);
lcd_puts(0, line++, buf);
lcd_update();
sleep(3*HZ);
lcd_puts(0, line++, "Woops, should not return from firmware!");
lcd_update();
goto usb;
}
load_rockbox:
map_memory();
lcd_puts(0, line, "Loading Rockbox...");
lcd_update();
sleep(HZ*4);
// TODO: read those values from somwhere
loadbuffer = (unsigned char*) 0x100;
buffer_size = (unsigned char*)0x400000 - loadbuffer;
rc=load_rockbox("/rockbox.gigabeat", loadbuffer, buffer_size);
if (rc < 0) {
snprintf(buf, sizeof(buf), "Rockbox error: %d",rc);
lcd_puts(0, line++, buf);
lcd_update();
} else {
lcd_puts(0, line++, "Rockbox loaded.");
lcd_update();
kernel_entry = (void*)0x100;
rc = kernel_entry();
snprintf(buf, sizeof(buf), "Woops, should not return from firmware: %d", rc);
lcd_puts(0, line++, buf);
lcd_update();
goto usb;
}
usb:
/* now wait in USB mode so the bootloader can be updated */ /* now wait in USB mode so the bootloader can be updated */
go_usb_mode(); go_usb_mode();
while(1); while(1);

View file

@ -136,6 +136,8 @@ drivers/rtc/rtc_pcf50606.c
drivers/rtc/rtc_pcf50605.c drivers/rtc/rtc_pcf50605.c
#elif (CONFIG_RTC == RTC_E8564) #elif (CONFIG_RTC == RTC_E8564)
drivers/rtc/rtc_e8564.c drivers/rtc/rtc_e8564.c
#elif (CONFIG_RTC == RTC_S3C2440)
drivers/rtc/rtc_s3c2440.c
#endif /* (CONFIG_RTC == RTC_) */ #endif /* (CONFIG_RTC == RTC_) */
#endif /* SIMULATOR */ #endif /* SIMULATOR */
@ -447,6 +449,12 @@ target/arm/gigabeat/meg-fx/power-meg-fx.c
target/arm/gigabeat/meg-fx/sc606-meg-fx.c target/arm/gigabeat/meg-fx/sc606-meg-fx.c
target/arm/gigabeat/meg-fx/usb-meg-fx.c target/arm/gigabeat/meg-fx/usb-meg-fx.c
target/arm/gigabeat/meg-fx/wmcodec-meg-fx.c target/arm/gigabeat/meg-fx/wmcodec-meg-fx.c
target/arm/gigabeat/meg-fx/dma_start.c
target/arm/gigabeat/meg-fx/system-meg-fx.c
target/arm/gigabeat/meg-fx/mmu-meg-fx.c
#ifndef BOOTLOADER
target/arm/gigabeat/meg-fx/pcm-meg-fx.c
#endif
#endif /* SIMULATOR */ #endif /* SIMULATOR */
#endif /* GIGABEAT_F */ #endif /* GIGABEAT_F */

View file

@ -45,9 +45,10 @@ INPUT(target/sh/crt0.o)
#define IRAMORIG 0x400000 #define IRAMORIG 0x400000
#define IRAMSIZE 0x7000 #define IRAMSIZE 0x7000
#elif CONFIG_CPU==S3C2440 #elif CONFIG_CPU==S3C2440
#define DRAMORIG 0x30000000 + STUBOFFSET #define DRAMORIG 0x100 + STUBOFFSET
#define IRAMORIG 0x40000000 #define IRAMORIG DRAMORIG
#define IRAMSIZE 4K #define IRAMSIZE 4K
#define IRAM DRAM
#else #else
#define DRAMORIG 0x09000000 + STUBOFFSET #define DRAMORIG 0x09000000 + STUBOFFSET
#define IRAMORIG 0x0f000000 #define IRAMORIG 0x0f000000
@ -63,7 +64,9 @@ INPUT(target/sh/crt0.o)
MEMORY MEMORY
{ {
DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
#if CONFIG_CPU != S3C2440
IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE
#endif
#if CONFIG_CPU==PNX0101 #if CONFIG_CPU==PNX0101
IRAM0 : ORIGIN = 0x0, LENGTH = IRAMSIZE IRAM0 : ORIGIN = 0x0, LENGTH = IRAMSIZE
#endif #endif
@ -146,6 +149,8 @@ SECTIONS
#if CONFIG_CPU==PNX0101 #if CONFIG_CPU==PNX0101
.iram IRAMORIG + SIZEOF(.vectors) : .iram IRAMORIG + SIZEOF(.vectors) :
#elif CONFIG_CPU==S3C2440
.iram :
#else #else
.iram IRAMORIG : .iram IRAMORIG :
#endif #endif
@ -200,7 +205,7 @@ SECTIONS
#if defined(CPU_COLDFIRE) #if defined(CPU_COLDFIRE)
.bss ADDR(.data) + SIZEOF(.data) + SIZEOF(.iram): .bss ADDR(.data) + SIZEOF(.data) + SIZEOF(.iram):
#elif defined(CPU_ARM) #elif defined(CPU_ARM) && CONFIG_CPU != S3C2440
.bss ADDR(.data) + SIZEOF(.data) + SIZEOF(.iram) + SIZEOF(.vectors): .bss ADDR(.data) + SIZEOF(.data) + SIZEOF(.iram) + SIZEOF(.vectors):
#else #else
.bss : .bss :

View file

@ -119,7 +119,7 @@ SECTIONS
} }
#elif (CONFIG_CPU==S3C2440) #elif (CONFIG_CPU==S3C2440)
{ {
. = DRAMORIG + 0x8000; . = DRAMORIG + 0x1000000;
.text : { .text : {
*(.init.text) *(.init.text)
*(.text) *(.text)

View file

@ -14,6 +14,12 @@
/* define this if you have a colour LCD */ /* define this if you have a colour LCD */
#define HAVE_LCD_COLOR 1 #define HAVE_LCD_COLOR 1
/* define this if you have access to the quickscreen */
#define HAVE_QUICKSCREEN
/* define this if you have access to the pitchscreen */
#define HAVE_PITCHSCREEN
/* define this if you would like tagcache to build on this target */ /* define this if you would like tagcache to build on this target */
#define HAVE_TAGCACHE #define HAVE_TAGCACHE
@ -30,14 +36,24 @@
#define CONFIG_CODEC SWCODEC #define CONFIG_CODEC SWCODEC
/* define this if you have a real-time clock */ /* define this if you have a real-time clock */
#if 0 /* TODO */
#define CONFIG_RTC RTC_S3C2440 #define CONFIG_RTC RTC_S3C2440
#endif
/* define this if the unit can be powered or charged via USB */
#define HAVE_USB_POWER
/* Define this for LCD backlight available */ /* Define this for LCD backlight available */
#define CONFIG_BACKLIGHT BL_GIGABEAT /* port controlled PWM */ #define CONFIG_BACKLIGHT BL_GIGABEAT /* port controlled PWM */
#define HAVE_BACKLIGHT_BRIGHTNESS
/* Main LCD backlight brightness range and defaults */
#define MIN_BRIGHTNESS_SETTING 0 /* 0.5 mA */
#define MIN_ACTIVE_BRIGHTNESS_SETTING 16 /* lowest active brightness */
#define MAX_DIM_BRIGHTNESS_SETTING 15 /* highest 'dimness' */
#define MAX_BRIGHTNESS_SETTING 63 /* 32 mA */
#define DEFAULT_BRIGHTNESS_SETTING 39 /* 20 mA */
#define DEFAULT_DIMNESS_SETTING 9 /* 5 mA */
/* Define this if you have a software controlled poweroff */ /* Define this if you have a software controlled poweroff */
#define HAVE_SW_POWEROFF #define HAVE_SW_POWEROFF
@ -54,23 +70,27 @@
#ifndef SIMULATOR #ifndef SIMULATOR
/* The LCD on a Gigabeat is 240x320 - it is portrait */
#define HAVE_PORTRAIT_LCD
/* Define this if you have a Motorola SCF5249 */ /* Define this if you have a Motorola SCF5249 */
#define CONFIG_CPU S3C2440 #define CONFIG_CPU S3C2440
/* Define this if you want to use coldfire's i2c interface */ /* Define this if you want to use coldfire's i2c interface */
#define CONFIG_I2C I2C_S3C2440 #define CONFIG_I2C I2C_S3C2440
/* Type of mobile power */ /* Type of mobile power - check this out */
#define CONFIG_BATTERY BATT_LIPOL1300 #define CONFIG_BATTERY BATT_LIION830 /* could change this later */
#define BATTERY_CAPACITY_MIN 1300 /* min. capacity selectable */ #define BATTERY_CAPACITY_MIN 750 /* min. capacity selectable */
#define BATTERY_CAPACITY_MAX 3200 /* max. capacity selectable */ #define BATTERY_CAPACITY_MAX 850 /* max. capacity selectable */
#define BATTERY_CAPACITY_INC 50 /* capacity increment */ #define BATTERY_CAPACITY_INC 25 /* capacity increment */
#define BATTERY_TYPES_COUNT 1 /* only one type */ #define BATTERY_TYPES_COUNT 1 /* only one type */
#define BATTERY_SCALE_FACTOR 6852 /* FIX: this value is picked at random */ /* ADC[0] is (530) at discharge and 625 at full charge */
#define BATTERY_SCALE_FACTOR 6450
/* Hardware controlled charging? FIXME */ /* Hardware controlled charging with monitoring */
#define CONFIG_CHARGING CHARGING_SIMPLE #define CONFIG_CHARGING CHARGING_MONITOR
/* define this if the hardware can be powered off while charging */ /* define this if the hardware can be powered off while charging */
#define HAVE_POWEROFF_WHILE_CHARGING #define HAVE_POWEROFF_WHILE_CHARGING
@ -82,9 +102,7 @@
#define CPU_FREQ 16934400 #define CPU_FREQ 16934400
/* Define this if you have ATA power-off control */ /* Define this if you have ATA power-off control */
#if 0 /* TODO */
#define HAVE_ATA_POWER_OFF #define HAVE_ATA_POWER_OFF
#endif
/* Virtual LED (icon) */ /* Virtual LED (icon) */
#define CONFIG_LED LED_VIRTUAL #define CONFIG_LED LED_VIRTUAL
@ -99,6 +117,7 @@
#define USB_GIGABEAT_STYLE #define USB_GIGABEAT_STYLE
#define HAVE_HEADPHONE_DETECTION
/* Define this if you have adjustable CPU frequency */ /* Define this if you have adjustable CPU frequency */
#if 0 /* TODO */ #if 0 /* TODO */
#define HAVE_ADJUSTABLE_CPU_FREQ #define HAVE_ADJUSTABLE_CPU_FREQ
@ -107,8 +126,5 @@
#define BOOTFILE_EXT "gigabeat" #define BOOTFILE_EXT "gigabeat"
#define BOOTFILE "rockbox." BOOTFILE_EXT #define BOOTFILE "rockbox." BOOTFILE_EXT
#if 0 /* TODO */
#define HAVE_BACKLIGHT_BRIGHTNESS
#endif
#endif #endif

View file

@ -74,6 +74,7 @@
#define BATT_LIPOL1300 1300 /* the type used in iRiver h1x0 models */ #define BATT_LIPOL1300 1300 /* the type used in iRiver h1x0 models */
#define BATT_LPCS355385 1550 /* iriver h10 20Gb - SKC LPCS355385 */ #define BATT_LPCS355385 1550 /* iriver h10 20Gb - SKC LPCS355385 */
#define BATT_BP009 820 /* iriver H10 5/6Gb - iriver BP009 */ #define BATT_BP009 820 /* iriver H10 5/6Gb - iriver BP009 */
#define BATT_LIION830 830 /* Toshiba Gigabeat Fxx and Xxx series MK11-2740 */
/* CONFIG_CHARGING */ /* CONFIG_CHARGING */
#define CHARGING_SIMPLE 1 /* Simple, hardware controlled charging */ #define CHARGING_SIMPLE 1 /* Simple, hardware controlled charging */

View file

@ -56,7 +56,7 @@ void kernel_init(void)
void sleep(int ticks) void sleep(int ticks)
{ {
#if CONFIG_CPU == S3C2440 && defined(BOOTLOADER) #if CONFIG_CPU == S3C2440 && defined(BOOTLOADER)
int counter; volatile int counter;
TCON &= ~(1 << 20); // stop timer 4 TCON &= ~(1 << 20); // stop timer 4
// TODO: this constant depends on dividers settings inherited from // TODO: this constant depends on dividers settings inherited from
// firmware. Set them explicitly somwhere. // firmware. Set them explicitly somwhere.
@ -76,7 +76,7 @@ void sleep(int ticks)
void yield(void) void yield(void)
{ {
#if (CONFIG_CPU == S3C2440 || defined(ELIO_TPJ1022) && defined(BOOTLOADER)) #if ((CONFIG_CPU == S3C2440 || defined(ELIO_TPJ1022)) && defined(BOOTLOADER))
/* Some targets don't like yielding in the bootloader */ /* Some targets don't like yielding in the bootloader */
#else #else
switch_thread(true, NULL); switch_thread(true, NULL);
@ -560,27 +560,34 @@ void tick_start(unsigned int interval_in_ms)
#elif CONFIG_CPU == S3C2440 #elif CONFIG_CPU == S3C2440
void tick_start(unsigned int interval_in_ms) void tick_start(unsigned int interval_in_ms)
{ {
unsigned long count; TCON &= ~(1 << 20); // stop timer 4
// TODO: this constant depends on dividers settings inherited from
// firmware. Set them explicitly somwhere.
TCNTB4 = 12193 * interval_in_ms / 1000;
TCON |= 1 << 21; // set manual bit
TCON &= ~(1 << 21); // reset manual bit
TCON |= 1 << 22; //interval mode
TCON |= (1 << 20); // start timer 4
/* period = (n + 1) / 128 , n = tick time count (1~127)*/ INTMOD &= ~(1 << 14); // timer 4 to IRQ mode
count = interval_in_ms / 1000 * 128 - 1; INTMSK &= ~(1 << 14); // timer 4 unmask interrupts
}
if(count > 127) void timer4(void) {
int i;
/* Run through the list of tick tasks */
for(i = 0; i < MAX_NUM_TICK_TASKS; i++)
{ {
panicf("Error! The tick interval is too long (%d ms)\n", if(tick_funcs[i])
interval_in_ms); {
return; tick_funcs[i]();
}
} }
/* Disable the tick */ current_tick++;
TICNT &= ~(1<<7);
/* Set the count value */
TICNT |= count;
/* Start up the ticker */
TICNT |= (1<<7);
/* need interrupt handler ??? */
/* following needs to be fixed. */
/*wake_up_thread();*/
} }
#endif #endif

View file

@ -59,46 +59,9 @@ void pcm_play_pause_unpause(void);
/** Functions that require targeted implementation **/ /** Functions that require targeted implementation **/
#ifndef CPU_COLDFIRE #if !defined(CPU_COLDFIRE) && (CONFIG_CPU != S3C2440)
#if (CONFIG_CPU == S3C2440) #if (CONFIG_CPU == PNX0101)
/* TODO: Implement for Gigabeat
For now, just implement some dummy functions.
*/
void pcm_init(void)
{
}
void pcm_play_dma_start(const void *addr, size_t size)
{
(void)addr;
(void)size;
}
void pcm_play_dma_stop(void)
{
}
void pcm_play_pause_pause(void)
{
}
void pcm_play_pause_unpause(void)
{
}
void pcm_set_frequency(unsigned int frequency)
{
(void)frequency;
}
size_t pcm_get_bytes_waiting(void)
{
return 0;
}
#elif (CONFIG_CPU == PNX0101)
#define DMA_BUF_SAMPLES 0x100 #define DMA_BUF_SAMPLES 0x100

View file

@ -191,6 +191,8 @@ static const unsigned int battery_level_dangerous[BATTERY_TYPES_COUNT] =
105, 115 105, 115
#elif CONFIG_BATTERY == BATT_LIPOL1300 /* iRiver H1x0: LiPolymer */ #elif CONFIG_BATTERY == BATT_LIPOL1300 /* iRiver H1x0: LiPolymer */
338 338
#elif CONFIG_BATTERY == BATT_LIION830 /* Gigabeat F */
340
#elif CONFIG_BATTERY == BATT_IAUDIO_X5 /* iAudio X5 */ #elif CONFIG_BATTERY == BATT_IAUDIO_X5 /* iAudio X5 */
354 354
#elif CONFIG_BATTERY == BATT_LPCS355385 /* iriver H10 20GB: LiPolymer*/ #elif CONFIG_BATTERY == BATT_LPCS355385 /* iriver H10 20GB: LiPolymer*/
@ -210,6 +212,8 @@ static const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
270, 280 270, 280
#elif CONFIG_BATTERY == BATT_LIPOL1300 /* iRiver Hxxx */ #elif CONFIG_BATTERY == BATT_LIPOL1300 /* iRiver Hxxx */
299 299
#elif CONFIG_BATTERY == BATT_LIION830 /* Gigabeat F */
338
#elif CONFIG_BATTERY == BATT_IAUDIO_X5 /* iAudio X5 */ #elif CONFIG_BATTERY == BATT_IAUDIO_X5 /* iAudio X5 */
350 350
#elif CONFIG_BATTERY == BATT_LPCS355385 /* iriver H10 20GB */ #elif CONFIG_BATTERY == BATT_LPCS355385 /* iriver H10 20GB */
@ -252,6 +256,9 @@ static const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
/* May need recalibration. */ /* May need recalibration. */
{ 93, 108, 114, 118, 121, 125, 128, 132, 136, 142, 158 }, /* alkaline */ { 93, 108, 114, 118, 121, 125, 128, 132, 136, 142, 158 }, /* alkaline */
{ 103, 118, 121, 123, 124, 125, 126, 127, 128, 129, 135 } /* NiMH */ { 103, 118, 121, 123, 124, 125, 126, 127, 128, 129, 135 } /* NiMH */
#elif CONFIG_BATTERY == BATT_LIION830
/* Toshiba Gigabeat Li Ion 830mAH figured from discharge curve */
{ 342, 358, 361, 368, 371, 374, 377, 381, 387, 390, 397 }
#else /* NiMH */ #else /* NiMH */
/* original values were taken directly after charging, but it should show /* original values were taken directly after charging, but it should show
100% after turning off the device for some hours, too */ 100% after turning off the device for some hours, too */
@ -263,12 +270,16 @@ static const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
#ifdef CONFIG_CHARGING #ifdef CONFIG_CHARGING
charger_input_state_type charger_input_state IDATA_ATTR; charger_input_state_type charger_input_state IDATA_ATTR;
/* voltages (centivolt) of 0%, 10%, ... 100% when charging enabled */ /* voltages (centivolt) of 0%, 10%, ... 100% when charging enabled */
static const unsigned short percent_to_volt_charge[11] = static const unsigned short percent_to_volt_charge[11] =
{ {
#if CONFIG_BATTERY == BATT_LIPOL1300 #if CONFIG_BATTERY == BATT_LIPOL1300
/* values measured over one full charging cycle */ /* values measured over one full charging cycle */
354, 386, 393, 398, 400, 402, 404, 408, 413, 418, 423 /* LiPo */ 354, 386, 393, 398, 400, 402, 404, 408, 413, 418, 423 /* LiPo */
#elif CONFIG_BATTERY == BATT_LIION830
/* Toshiba Gigabeat Li Ion 830mAH */
347, 363, 366, 373, 376, 379, 382, 386, 393, 403, 411
#elif CONFIG_BATTERY == BATT_LPCS355385 #elif CONFIG_BATTERY == BATT_LPCS355385
/* iriver H10 20GB */ /* iriver H10 20GB */
399, 403, 406, 408, 410, 412, 415, 418, 422, 426, 431 399, 403, 406, 408, 410, 412, 415, 418, 422, 426, 431

View file

@ -86,7 +86,15 @@ void cpu_idle_mode(bool on_off)
void system_reboot(void) { void system_reboot(void) {
} }
void system_init(void) { void system_init(void)
{
/* Turn off un-needed devices */
/* Turn off all of the UARTS */
CLKCON &= ~( (1<<10) | (1<<11) |(1<<12) );
/* Turn off AC97 and Camera */
CLKCON &= ~( (1<<19) | (1<<20) );
} }
#endif #endif

View file

@ -122,6 +122,25 @@ start:
/* Code for ARM bootloader targets other than iPod go here */ /* Code for ARM bootloader targets other than iPod go here */
#if CONFIG_CPU == S3C2440 #if CONFIG_CPU == S3C2440
/* get the high part of our execute address */
ldr r2, =0xffffff00
and r4, pc, r2
/* Copy bootloader to safe area - 0x31000000 */
mov r5, #0x30000000
add r5, r5, #0x1000000
ldr r6, = _dataend
sub r0, r6, r5 /* length of loader */
add r0, r4, r0 /* r0 points to start of loader */
1:
cmp r5, r6
ldrcc r2, [r4], #4
strcc r2, [r5], #4
bcc 1b
ldr pc, =start_loc /* jump to the relocated start_loc: */
start_loc:
bl main bl main
#endif #endif
@ -201,7 +220,10 @@ prefetch_abort_handler:
fiq_handler: fiq_handler:
@ Branch straight to FIQ handler in pcm_playback.c. This also handles the @ Branch straight to FIQ handler in pcm_playback.c. This also handles the
@ the correct return sequence. @ the correct return sequence.
ldr pc, =fiq stmfd sp!, {r0-r7, r12, lr}
bl fiq
ldmfd sp!, {r0-r7, r12, lr}
subs pc, lr, #4
data_abort_handler: data_abort_handler:
sub r0, lr, #8 sub r0, lr, #8
@ -210,9 +232,9 @@ data_abort_handler:
irq_handler: irq_handler:
#ifndef STUB #ifndef STUB
stmfd sp!, {r0-r3, r12, lr} stmfd sp!, {r0-r11, r12, lr}
bl irq bl irq
ldmfd sp!, {r0-r3, r12, lr} ldmfd sp!, {r0-r11, r12, lr}
#endif #endif
subs pc, lr, #4 subs pc, lr, #4

View file

@ -18,24 +18,67 @@
****************************************************************************/ ****************************************************************************/
#include "cpu.h" #include "cpu.h"
#include "adc-target.h" #include "adc-target.h"
#include "kernel.h"
void adc_init(void) {
static unsigned short adc_readings[NUM_ADC_CHANNELS];
/* prototypes */
static unsigned short __adc_read(int channel);
static void adc_tick(void);
void adc_init(void)
{
int i;
/* Turn on the ADC PCLK */ /* Turn on the ADC PCLK */
CLKCON |= (1<<15); CLKCON |= (1<<15);
/* Set channel 0, normal mode, disable "start by read" */ /* Set channel 0, normal mode, disable "start by read" */
ADCCON &= ~(0x3F); ADCCON &= ~(0x3F);
/* No start delay. Use nromal conversion mode. */ /* No start delay. Use normal conversion mode. */
ADCDLY |= 0x1; ADCDLY = 0x1;
/* Set and enable the prescaler */ /* Set and enable the prescaler */
ADCCON = (ADCCON & ~(0xff<<6)) | (0x19<<6); ADCCON = (ADCCON & ~(0xff<<6)) | (0x19<<6);
ADCCON |= (1<<14); ADCCON |= (1<<14);
/* prefill the adc channels */
for (i = 0; i < NUM_ADC_CHANNELS; i++)
{
adc_readings[i] = __adc_read(i);
}
/* start at zero so when the tick starts it is at zero */
adc_readings[0] = __adc_read(0);
/* attach the adc reading to the tick */
tick_add_task(adc_tick);
} }
unsigned short adc_read(int channel) {
/* Called to get the recent ADC reading */
inline unsigned short adc_read(int channel)
{
return adc_readings[channel];
}
/**
* Read the ADC by polling
* @param channel The ADC channel to read
* @return 10bit reading from ADC channel or ADC_READ_ERROR if timeout
*/
static unsigned short __adc_read(int channel)
{
int i; int i;
/* Set the channel */ /* Set the channel */
@ -45,34 +88,57 @@ unsigned short adc_read(int channel) {
ADCCON |= 0x1; ADCCON |= 0x1;
/* Wait for a low Enable_start */ /* Wait for a low Enable_start */
i = 20000; for (i = 20000;;) {
while(i > 0) { if(0 == (ADCCON & 0x1)) {
if(ADCCON & 0x1) {
i--;
}
else {
break; break;
} }
} else {
if(i == 0) { i--;
if (0 == i) {
/* Ran out of time */ /* Ran out of time */
return(0); return ADC_READ_ERROR;
}
}
} }
/* Wait for high End_of_Conversion */ /* Wait for high End_of_Conversion */
i = 20000; for(i = 20000;;) {
while(i > 0) {
if(ADCCON & (1<<15)) { if(ADCCON & (1<<15)) {
break; break;
} }
else { else {
i--; i--;
} if(0 == i) {
}
if(i == 0) {
/* Ran out of time */ /* Ran out of time */
return(0); return ADC_READ_ERROR;
}
}
} }
return(ADCDAT0 & 0x3ff); return (ADCDAT0 & 0x3ff);
} }
/* add this to the tick so that the ADC converts are done in the background */
static void adc_tick(void)
{
static unsigned channel;
/* Check if the End Of Conversion is set */
if (ADCCON & (1<<15))
{
adc_readings[channel] = (ADCDAT0 & 0x3FF);
if (++channel >= NUM_ADC_CHANNELS)
{
channel = 0;
}
/* setup the next conversion and start it*/
ADCCON = (ADCCON & ~(0x7<<3)) | (channel<<3) | 0x01;
}
}

View file

@ -19,12 +19,19 @@
#ifndef _ADC_TARGET_H_ #ifndef _ADC_TARGET_H_
#define _ADC_TARGET_H_ #define _ADC_TARGET_H_
#define NUM_ADC_CHANNELS 4 /* only two channels used by the Gigabeat */
#define NUM_ADC_CHANNELS 2
#define ADC_BATTERY 0 #define ADC_BATTERY 0
#define ADC_UNKNOWN_2 1 #define ADC_HPREMOTE 1
#define ADC_UNKNOWN_3 2 #define ADC_UNKNOWN_3 2
#define ADC_UNKNOWN_4 3 #define ADC_UNKNOWN_4 3
#define ADC_UNKNOWN_5 4
#define ADC_UNKNOWN_6 5
#define ADC_UNKNOWN_7 6
#define ADC_UNKNOWN_8 7
#define ADC_UNREG_POWER ADC_BATTERY /* For compatibility */ #define ADC_UNREG_POWER ADC_BATTERY /* For compatibility */
#define ADC_READ_ERROR 0xFFFF
#endif #endif

View file

@ -26,11 +26,18 @@
void ata_reset(void) void ata_reset(void)
{ {
GPGDAT &= ~(1 << 10);
sleep(1); /* > 25us */
GPGDAT |= (1 << 10);
sleep(1); /* > 2ms */
} }
void ata_enable(bool on) void ata_enable(bool on)
{ {
(void)on; if(on)
GPGDAT &= ~(1 << 12);
else
GPGDAT |= (1 << 12);
} }
bool ata_is_coldstart(void) bool ata_is_coldstart(void)

View file

@ -20,6 +20,8 @@
#define ATA_TARGET_H #define ATA_TARGET_H
/* Plain C read & write loops */ /* Plain C read & write loops */
#define PREFER_C_READING
#define PREFER_C_WRITING
#define ATA_IOBASE 0x18000000 #define ATA_IOBASE 0x18000000
#define ATA_DATA (*((volatile unsigned short*)(ATA_IOBASE))) #define ATA_DATA (*((volatile unsigned short*)(ATA_IOBASE)))

View file

@ -19,11 +19,16 @@
#include "config.h" #include "config.h"
#include "cpu.h" #include "cpu.h"
#include "system.h" #include "system.h"
#include "backlight-target.h"
#include "backlight.h" #include "backlight.h"
#include "lcd.h" #include "lcd.h"
#include "sc606-meg-fx.h" #include "sc606-meg-fx.h"
int confval = SC606_LOW_FREQ; static int confval = SC606_LOW_FREQ;
void __backlight_init(void)
{
}
void __backlight_on(void) void __backlight_on(void)
{ {

View file

@ -19,6 +19,7 @@
#ifndef BACKLIGHT_TARGET_H #ifndef BACKLIGHT_TARGET_H
#define BACKLIGHT_TARGET_H #define BACKLIGHT_TARGET_H
void __backlight_init(void);
void __backlight_on(void); void __backlight_on(void);
void __backlight_off(void); void __backlight_off(void);
void __backlight_set_brightness(int val); void __backlight_set_brightness(int val);

View file

@ -27,27 +27,76 @@
#include "adc.h" #include "adc.h"
#include "system.h" #include "system.h"
static bool headphones_detect;
static int const remote_buttons[] =
{
BUTTON_NONE, /* Headphones connected - remote disconnected */
BUTTON_SELECT,
BUTTON_MENU, /* could be changed to BUTTON_A */
BUTTON_LEFT,
BUTTON_RIGHT,
BUTTON_UP, /* could be changed to BUTTON_VOL_UP */
BUTTON_DOWN, /* could be changed to BUTTON_VOL_DOWN */
BUTTON_NONE, /* Remote control attached - no buttons pressed */
BUTTON_NONE, /* Nothing in the headphone socket */
};
void button_init_device(void) void button_init_device(void)
{ {
/* Power, Remote Play & Hold switch */ /* Power, Remote Play & Hold switch */
} }
bool button_hold(void)
inline bool button_hold(void)
{ {
return (GPGDAT & (1 << 15)); return (GPGDAT & (1 << 15));
} }
int button_read_device(void) int button_read_device(void)
{ {
int btn = BUTTON_NONE; int btn;
int touchpad = GPJDAT; int touchpad;
int buttons = GPGDAT; int buttons;
static int lastbutton;
unsigned short remote_adc;
/* Check for hold first */ /* Check for hold first - exit if asserted with no button pressed */
if (buttons & (1 << 15)) if (button_hold())
return btn; return BUTTON_NONE;
/* the side buttons */ /* See header for ADC values when remote control buttons are pressed */
/* Only one button can be sensed at a time on the remote. */
/* Need to filter the remote button because the ADC is so fast */
remote_adc = adc_read(ADC_HPREMOTE);
btn = remote_buttons[(remote_adc + 64) / 128];
if (btn != lastbutton)
{
/* if the buttons dont agree twice in a row, then its none */
lastbutton = btn;
btn = BUTTON_NONE;
}
/*
* Code can be added that overrides the side buttons when the remote is
* plugged in: Check for remote_adc > 64 && remote_adc < 930 then skip
* reading the side and touch volume buttons, right, left, up, down, etc.
* but keep reading the Power and 'A'.
* For now, the buttons from remote and side and touch are used together.
*/
/* the side buttons - Check before doing all of the work on each bit */
buttons = GPGDAT & 0x1F;
if (buttons)
{
if (buttons & (1 << 0)) if (buttons & (1 << 0))
btn |= BUTTON_POWER; btn |= BUTTON_POWER;
@ -62,8 +111,12 @@ int button_read_device(void)
if (buttons & (1 << 4)) if (buttons & (1 << 4))
btn |= BUTTON_A; btn |= BUTTON_A;
}
/* the touchpad */ /* the touchpad */
touchpad = GPJDAT & 0x10C9;
if (touchpad)
{
if (touchpad & (1 << 0)) if (touchpad & (1 << 0))
btn |= BUTTON_UP; btn |= BUTTON_UP;
@ -78,7 +131,23 @@ int button_read_device(void)
if (touchpad & (1 << 3)) if (touchpad & (1 << 3))
btn |= BUTTON_SELECT; btn |= BUTTON_SELECT;
}
return btn; return btn;
} }
bool headphones_inserted(void)
{
unsigned short remote_adc = adc_read(ADC_HPREMOTE);
if (remote_adc != ADC_READ_ERROR)
{
/* If there is nothing in the headphone socket, the ADC reads high */
if (remote_adc < 940)
headphones_detect = true;
else
headphones_detect = false;
}
return headphones_detect;
}

View file

@ -45,6 +45,37 @@ int button_read_device(void);
#define BUTTON_A 0x00000200 #define BUTTON_A 0x00000200
/* Toshiba Gigabeat specific remote button ADC values */
/* The remote control uses ADC 1 to emulate button pushes
Reading (approx) Button HP plugged in? Remote plugged in?
0 N/A Yes No
125 Play/Pause Cant tell Yes
241 Speaker+ Cant tell Yes
369 Rewind Cant tell Yes
492 Fast Fwd Cant tell Yes
616 Vol + Cant tell Yes
742 Vol - Cant tell Yes
864 None Cant tell Yes
1023 N/A No No
*/
/*
Notes:
Buttons on the remote are translated into equivalent button presses just
as if you were pressing them on the Gigabeat itself.
We cannot tell if the hold is asserted on the remote. The Hold function on
the remote is to block the output of the buttons changing.
Only one button can be sensed at a time. If another is pressed, the button
with the lowest reading is dominant. So, if Rewind and Vol + are pressed
at the same time, Rewind value is the one that is read.
*/
#define BUTTON_MAIN (BUTTON_POWER|BUTTON_MENU|BUTTON_LEFT|BUTTON_RIGHT\ #define BUTTON_MAIN (BUTTON_POWER|BUTTON_MENU|BUTTON_LEFT|BUTTON_RIGHT\
|BUTTON_UP|BUTTON_DOWN|BUTTON_VOL_UP|BUTTON_VOL_DOWN\ |BUTTON_UP|BUTTON_DOWN|BUTTON_VOL_UP|BUTTON_VOL_DOWN\
|BUTTON_SELECT|BUTTON_A) |BUTTON_SELECT|BUTTON_A)

View file

@ -0,0 +1,8 @@
#include <sys/types.h>
void dma_start(const void* addr, size_t size) {
(void) addr;
(void) size;
//TODO:
}

View file

@ -0,0 +1,25 @@
#include "kernel.h"
#include "thread.h"
#include <stdio.h>
#include "lcd.h"
extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void);
void timer4(void) {
int i;
/* 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++;
/* following needs to be fixed. */
/*wake_up_thread();*/
}

View file

@ -1,27 +1,56 @@
#include "config.h" #include "config.h"
#include <string.h>
#include "cpu.h" #include "cpu.h"
#include "lcd.h" #include "lcd.h"
#include "kernel.h" #include "kernel.h"
#include "system.h" #include "system.h"
#include "string.h"
void lcd_init_device(void); void lcd_init_device(void);
void lcd_update_rec(int, int, int, int); void lcd_update_rec(int, int, int, int);
void lcd_update(void); void lcd_update(void);
bool usedmablit = false;
/* LCD init */ /* LCD init */
void lcd_init_device(void) void lcd_init_device(void)
{ {
/* Switch from 555I mode to 565 mode */
LCDCON5 |= 1 << 11;
} }
/* Update a fraction of the display. */ /* Update a fraction of the display. */
void lcd_update_rect(int x, int y, int width, int height) void lcd_update_rect(int x, int y, int width, int height)
{ {
(void)x; (void)x;
(void)y;
(void)width; (void)width;
(void)height;
memcpy(FRAME, &lcd_framebuffer, sizeof(lcd_framebuffer)); if (usedmablit)
{
/* Spin waiting for DMA to become available */
//while (DSTAT0 & (1<<20)) ;
if (DSTAT0 & (1<<20)) return;
/* set DMA dest */
DIDST0 = (int) FRAME + y * sizeof(fb_data) * LCD_WIDTH;
/* FRAME on AHB buf, increment */
DIDSTC0 = 0;
DCON0 = (((1<<30) | (1<<28) | (1<<27) | (1<<22) | (2<<20)) | ((height * sizeof(fb_data) * LCD_WIDTH) >> 4));
/* set DMA source and options */
DISRC0 = (int) &lcd_framebuffer + (y * sizeof(fb_data) * LCD_WIDTH) + 0x30000000;
DISRCC0 = 0x00; /* memory is on AHB bus, increment addresses */
/* Activate the channel */
DMASKTRIG0 = 0x2;
/* Start DMA */
DMASKTRIG0 |= 0x1;
}
else
{
memcpy((void*)FRAME, &lcd_framebuffer, sizeof(lcd_framebuffer));
}
} }
/* Update the display. /* Update the display.
@ -44,6 +73,138 @@ void lcd_update(void)
#define ROUNDOFFS (127*257) #define ROUNDOFFS (127*257)
/* Performance function to blit a YUV bitmap directly to the LCD */
/* For the Gigabeat - show it rotated */
/* So the LCD_WIDTH is now the height */
void lcd_yuv_blit(unsigned char * const src[3],
int src_x, int src_y, int stride,
int x, int y, int width, int height)
{
width = (width + 1) & ~1;
fb_data *dst = (fb_data*)FRAME + x * LCD_WIDTH + (LCD_WIDTH - y) - 1;
fb_data *dst_last = dst - (height - 1);
for (;;)
{
fb_data *dst_row = dst;
int count = width;
const unsigned char *ysrc = src[0] + stride * src_y + src_x;
int y, u, v;
int red, green, blue;
unsigned rbits, gbits, bbits;
/* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
const unsigned char *usrc = src[1] + (stride/CSUB_X) * (src_y/CSUB_Y)
+ (src_x/CSUB_X);
const unsigned char *vsrc = src[2] + (stride/CSUB_X) * (src_y/CSUB_Y)
+ (src_x/CSUB_X);
int xphase = src_x % CSUB_X;
int rc, gc, bc;
u = *usrc++ - 128;
v = *vsrc++ - 128;
rc = RVFAC * v + ROUNDOFFS;
gc = GVFAC * v + GUFAC * u + ROUNDOFFS;
bc = BUFAC * u + ROUNDOFFS;
do
{
y = *ysrc++;
red = RYFAC * y + rc;
green = GYFAC * y + gc;
blue = BYFAC * y + bc;
if ((unsigned)red > (RYFAC*255+ROUNDOFFS))
{
if (red < 0)
red = 0;
else
red = (RYFAC*255+ROUNDOFFS);
}
if ((unsigned)green > (GYFAC*255+ROUNDOFFS))
{
if (green < 0)
green = 0;
else
green = (GYFAC*255+ROUNDOFFS);
}
if ((unsigned)blue > (BYFAC*255+ROUNDOFFS))
{
if (blue < 0)
blue = 0;
else
blue = (BYFAC*255+ROUNDOFFS);
}
rbits = ((unsigned)red) >> 16 ;
gbits = ((unsigned)green) >> 16 ;
bbits = ((unsigned)blue) >> 16 ;
*dst_row = (rbits << 11) | (gbits << 5) | bbits;
/* next pixel - since rotated, add WIDTH */
dst_row += LCD_WIDTH;
if (++xphase >= CSUB_X)
{
u = *usrc++ - 128;
v = *vsrc++ - 128;
rc = RVFAC * v + ROUNDOFFS;
gc = GVFAC * v + GUFAC * u + ROUNDOFFS;
bc = BUFAC * u + ROUNDOFFS;
xphase = 0;
}
}
while (--count);
if (dst == dst_last) break;
dst--;
src_y++;
}
}
void lcd_set_contrast(int val) {
(void) val;
// TODO:
}
void lcd_set_invert_display(bool yesno) {
(void) yesno;
// TODO:
}
void lcd_blit(const fb_data* data, int bx, int y, int bwidth,
int height, int stride)
{
(void) data;
(void) bx;
(void) y;
(void) bwidth;
(void) height;
(void) stride;
//TODO:
}
void lcd_set_flip(bool yesno) {
(void) yesno;
// TODO:
}
#if 0
/* Performance function to blit a YUV bitmap directly to the LCD */ /* Performance function to blit a YUV bitmap directly to the LCD */
void lcd_yuv_blit(unsigned char * const src[3], void lcd_yuv_blit(unsigned char * const src[3],
int src_x, int src_y, int stride, int src_x, int src_y, int stride,
@ -129,3 +290,7 @@ void lcd_yuv_blit(unsigned char * const src[3],
} }
while (dst < dst_end); while (dst < dst_end);
} }
#endif

View file

@ -0,0 +1,84 @@
#include <string.h>
#include "s3c2440.h"
void map_memory(void);
static void enable_mmu(void);
static void set_ttb(void);
static void set_page_tables(void);
static void map_section(unsigned int pa, unsigned int va, int mb, int cache_flags);
#define SECTION_ADDRESS_MASK (-1 << 20)
#define CACHE_ALL (1 << 3 | 1 << 2 )
#define CACHE_NONE 0
#define BUFFERED (1 << 2)
#define MB (1 << 20)
void map_memory(void) {
set_ttb();
set_page_tables();
enable_mmu();
}
unsigned int* ttb_base;
const int ttb_size = 4096;
void set_ttb() {
int i;
int* ttbPtr;
int domain_access;
/* must be 16Kb (0x4000) aligned */
ttb_base = (int*)0x31F00000;
for (i=0; i<ttb_size; i++,ttbPtr++)
ttbPtr = 0;
asm volatile("mcr p15, 0, %0, c2, c0, 0" : : "r" (ttb_base));
/* set domain D0 to "client" permission access */
domain_access = 3;
asm volatile("mcr p15, 0, %0, c3, c0, 0" : : "r" (domain_access));
}
void set_page_tables() {
map_section(0, 0, 0x1000, CACHE_NONE);
map_section(0x30000000, 0, 32, CACHE_NONE); /* map RAM to 0 */
map_section(0x30000000, 0, 30, CACHE_ALL); /* cache the first 30 MB or RAM */
map_section(0x31E00000, 0x31E00000, 1, BUFFERED); /* enable buffered writing for the framebuffer */
}
void map_section(unsigned int pa, unsigned int va, int mb, int cache_flags) {
unsigned int* ttbPtr;
int i;
int section_no;
section_no = va >> 20; /* sections are 1Mb size */
ttbPtr = ttb_base + section_no;
pa &= SECTION_ADDRESS_MASK; /* align to 1Mb */
for(i=0; i<mb; i++, pa += MB) {
*(ttbPtr + i) =
pa |
1 << 10 | /* superuser - r/w, user - no access */
0 << 5 | /* domain 0th */
1 << 4 | /* should be "1" */
cache_flags |
1 << 1; /* Section signature */
}
}
static void enable_mmu(void) {
asm volatile("mov r0, #0\n"
"mcr p15, 0, r0, c8, c7, 0\n" /* invalidate TLB */
"mcr p15, 0, r0, c7, c7,0\n" /* invalidate both icache and dcache */
"mrc p15, 0, r0, c1, c0, 0\n"
"orr r0, r0, #1<<0\n" /* enable mmu bit, icache and dcache */
"orr r0, r0, #1<<2\n" /* enable dcache */
"orr r0, r0, #1<<12\n" /* enable icache */
"mcr p15, 0, r0, c1, c0, 0" : : : "r0");
asm volatile("nop \n nop \n nop \n nop");
}

View file

@ -0,0 +1,347 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2006 by Michael Sevakis
*
* 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 "system.h"
#include "kernel.h"
#include "logf.h"
#include "audio.h"
#include "wm8975.h"
#include "file.h"
static int pcm_freq = HW_SAMPR_DEFAULT; /* 44.1 is default */
#define FIFO_COUNT ((IISFCON >> 6) & 0x01F)
/* number of bytes in FIFO */
#define IIS_FIFO_SIZE 64
/* Setup for the DMA controller */
#define DMA_CONTROL_SETUP ((1<<31) | (1<<29) | (1<<23) | (1<<22) | (1<<20))
unsigned short * p;
size_t p_size;
/* DMA count has hit zero - no more data */
/* Get more data from the callback and top off the FIFO */
//void fiq(void) __attribute__ ((interrupt ("naked")));
void fiq(void) ICODE_ATTR __attribute__ ((interrupt ("FIQ")));
void fiq(void)
{
/* clear any pending interrupt */
SRCPND = (1<<19);
/* Buffer empty. Try to get more. */
if (pcm_callback_for_more)
{
pcm_callback_for_more((unsigned char**)&p, &p_size);
}
else
{
/* callback func is missing? */
pcm_play_dma_stop();
return;
}
if (p_size)
{
/* set the new DMA values */
DCON2 = DMA_CONTROL_SETUP | (p_size >> 1);
DISRC2 = (int)p + 0x30000000;
/* Re-Activate the channel */
DMASKTRIG2 = 0x2;
}
else
{
/* No more DMA to do */
pcm_play_dma_stop();
}
}
void pcm_init(void)
{
pcm_playing = false;
pcm_paused = false;
pcm_callback_for_more = NULL;
audiohw_init();
audiohw_enable_output(true);
audiohw_mute(true);
/* cannot use the WM8975 defaults since our clock is not the same */
/* the input master clock is 16.9344MHz - we can divide exact for that */
audiohw_set_sample_rate( (0<<6) | (0x11 << 1) | (0<<0));
/* init GPIO */
GPCCON = (GPCCON & ~(3<<14)) | (1<<14);
GPCDAT |= 1<<7;
GPECON |= 0x2aa;
/* Do no service DMA0 requests, yet */
/* clear any pending int and mask it */
INTMSK |= (1<<19); /* mask the interrupt */
SRCPND = (1<<19); /* clear any pending interrupts */
INTMOD |= (1<<19); /* connect to FIQ */
}
void pcm_play_dma_start(const void *addr, size_t size)
{
//FIXME
//return;
int i;
/* sanity check: bad pointer or too small file */
if ((NULL == addr) || (size & ~1) <= IIS_FIFO_SIZE) return;
p = (unsigned short *)addr;
p_size = size;
/* Enable the IIS clock */
CLKCON |= (1<<17);
/* IIS interface setup and set to idle */
IISCON = (1<<5) | (1<<3);
/* slave, transmit mode, 16 bit samples - 384fs - use 16.9344Mhz */
IISMOD = (1<<9) | (1<<8) | (2<<6) | (1<<3) | (1<<2);
/* connect DMA to the FIFO and enable the FIFO */
IISFCON = (1<<15) | (1<<13);
/* prefill the FIFO with half words */
for (i=0; i < IIS_FIFO_SIZE; i+=2)
{
IISFIFO = *p++;
p_size -= 2;
}
/* set DMA dest */
DIDST2 = (int)&IISFIFO;
/* IIS is on the APB bus, INT when TC reaches 0, fixed dest addr */
DIDSTC2 = 0x03;
/* How many transfers to make - we transfer half-word at a time = 2 bytes */
/* DMA control: CURR_TC int, single service mode, I2SSDO int, HW trig */
/* no auto-reload, half-word (16bit) */
DCON2 = DMA_CONTROL_SETUP | (p_size / 2);
/* set DMA source and options */
DISRC2 = (int)p + 0x30000000;
DISRCC2 = 0x00; /* memory is on AHB bus, increment addresses */
/* clear pending DMA interrupt */
SRCPND = 1<<19;
enable_fiq(fiq);
/* unmask the DMA interrupt */
INTMSK &= ~(1<<19);
/* Activate the channel */
DMASKTRIG2 = 0x2;
/* turn off the idle */
IISCON &= ~(1<<3);
pcm_playing = true;
/* start the IIS */
IISCON |= (1<<0);
}
/* Disconnect the DMA and wait for the FIFO to clear */
void pcm_play_dma_stop(void)
{
pcm_playing = false;
/* mask the DMA interrupt */
INTMSK |= (1<<19);
/* De-Activate the channel */
DMASKTRIG2 = 0x4;
/* idle the IIS transmit */
IISCON |= (1<<3);
/* stop the IIS interface */
IISCON &= ~(1<<0);
/* Disconnect the IIS IIS clock */
CLKCON &= ~(1<<17);
disable_fiq();
}
void pcm_play_pause_pause(void)
{
/* idle */
IISCON |= (1<<3);
}
void pcm_play_pause_unpause(void)
{
/* no idle */
IISCON &= ~(1<<3);
}
void pcm_set_frequency(unsigned int frequency)
{
int sr_ctrl;
switch(frequency)
{
case SAMPR_11:
sr_ctrl = 0x19 << 1;
break;
case SAMPR_22:
sr_ctrl = 0x1B << 1;
break;
default:
case SAMPR_44:
sr_ctrl = 0x11 << 1;
break;
case SAMPR_88:
sr_ctrl = 0x1F << 1;
break;
}
audiohw_set_sample_rate(sr_ctrl);
pcm_freq = frequency;
}
size_t pcm_get_bytes_waiting(void)
{
return (DSTAT2 & 0xFFFFF) * 2;
}
/* dummy functions for those not actually supporting all this yet */
void pcm_apply_settings(bool reset)
{
(void)reset;
}
void pcm_set_monitor(int monitor)
{
(void)monitor;
}
/** **/
void pcm_mute(bool mute)
{
audiohw_mute(mute);
if (mute)
sleep(HZ/16);
}
/*
* This function goes directly into the DMA buffer to calculate the left and
* right peak values. To avoid missing peaks it tries to look forward two full
* peek periods (2/HZ sec, 100% overlap), although it's always possible that
* the entire period will not be visible. To reduce CPU load it only looks at
* every third sample, and this can be reduced even further if needed (even
* every tenth sample would still be pretty accurate).
*/
/* Check for a peak every PEAK_STRIDE samples */
#define PEAK_STRIDE 3
/* Up to 1/50th of a second of audio for peak calculation */
/* This should use NATIVE_FREQUENCY, or eventually an adjustable freq. value */
#define PEAK_SAMPLES (44100/50)
void pcm_calculate_peaks(int *left, int *right)
{
short *addr;
short *end;
{
size_t samples = p_size / 4;
addr = p;
if (samples > PEAK_SAMPLES)
samples = PEAK_SAMPLES - (PEAK_STRIDE - 1);
else
samples -= MIN(PEAK_STRIDE - 1, samples);
end = &addr[samples * 2];
}
if (left && right) {
int left_peak = 0, right_peak = 0;
while (addr < end) {
int value;
if ((value = addr [0]) > left_peak)
left_peak = value;
else if (-value > left_peak)
left_peak = -value;
if ((value = addr [PEAK_STRIDE | 1]) > right_peak)
right_peak = value;
else if (-value > right_peak)
right_peak = -value;
addr = &addr[PEAK_STRIDE * 2];
}
*left = left_peak;
*right = right_peak;
}
else if (left || right) {
int peak_value = 0, value;
if (right)
addr += (PEAK_STRIDE | 1);
while (addr < end) {
if ((value = addr [0]) > peak_value)
peak_value = value;
else if (-value > peak_value)
peak_value = -value;
addr += PEAK_STRIDE * 2;
}
if (left)
*left = peak_value;
else
*right = peak_value;
}
}

View file

@ -23,6 +23,8 @@
#include "system.h" #include "system.h"
#include "power.h" #include "power.h"
#include "pcf50606.h" #include "pcf50606.h"
#include "backlight.h"
#include "backlight-target.h"
#ifndef SIMULATOR #ifndef SIMULATOR
@ -33,21 +35,34 @@ void power_init(void)
bool charger_inserted(void) bool charger_inserted(void)
{ {
return !(GPFDAT & (1 << 4)); return (GPFDAT & (1 << 4)) ? false : true;
}
/* Returns true if the unit is charging the batteries. */
bool charging_state(void) {
return (GPGDAT & (1 << 8)) ? false : true;
} }
void ide_power_enable(bool on) void ide_power_enable(bool on)
{ {
(void)on; if (on)
GPGDAT |= (1 << 11);
else
GPGDAT &= ~(1 << 11);
} }
bool ide_powered(void) bool ide_powered(void)
{ {
return true; return (GPGDAT & (1 << 11)) != 0;
} }
void power_off(void) void power_off(void)
{ {
/* turn off backlight and wait for 1 second */
__backlight_off();
sleep(HZ/2);
/* set SLEEP bit to on in CLKCON to turn off */
CLKCON |=(1<<3);
} }
#else /* SIMULATOR */ #else /* SIMULATOR */

View file

@ -24,10 +24,11 @@
#define SCL_SDA_HI GPHDAT |= (3 << 9) #define SCL_SDA_HI GPHDAT |= (3 << 9)
/* arbitrary delay loop */ /* The SC606 can clock at 400KHz: 2.5uS period -> 1.25uS half period */
#define DELAY do { int _x; for(_x=0;_x<2000;_x++);} while (0) /* At 300Mhz - if loop takes 6 cycles @ 3.3nS each -> 1.25uS / 20nS -> 63 */
#define DELAY do { volatile int _x; for(_x=0;_x<63;_x++);} while (0)
void sc606_i2c_start(void) static void sc606_i2c_start(void)
{ {
SCL_SDA_HI; SCL_SDA_HI;
DELAY; DELAY;
@ -36,7 +37,7 @@ void sc606_i2c_start(void)
SCL_LO; SCL_LO;
} }
void sc606_i2c_restart(void) static void sc606_i2c_restart(void)
{ {
SCL_SDA_HI; SCL_SDA_HI;
DELAY; DELAY;
@ -45,7 +46,7 @@ void sc606_i2c_restart(void)
SCL_LO; SCL_LO;
} }
void sc606_i2c_stop(void) static void sc606_i2c_stop(void)
{ {
SDA_LO; SDA_LO;
DELAY; DELAY;
@ -55,7 +56,7 @@ void sc606_i2c_stop(void)
DELAY; DELAY;
} }
void sc606_i2c_ack(void) static void sc606_i2c_ack(void)
{ {
SDA_LO; SDA_LO;
@ -64,11 +65,11 @@ void sc606_i2c_ack(void)
SCL_LO; SCL_LO;
} }
int sc606_i2c_getack(void) static int sc606_i2c_getack(void)
{ {
int ret = 0; int ret = 0;
/* Don't need a delay since this follows a data bit with a delay on the end */ /* Don't need a delay since follows a data bit with a delay on the end */
SDA_INPUT; /* And set to input */ SDA_INPUT; /* And set to input */
SCL_HI; SCL_HI;
DELAY; DELAY;
@ -83,7 +84,7 @@ int sc606_i2c_getack(void)
return ret; return ret;
} }
int sc606_i2c_outb(unsigned char byte) static int sc606_i2c_outb(unsigned char byte)
{ {
int i; int i;
@ -106,7 +107,7 @@ int sc606_i2c_outb(unsigned char byte)
return sc606_i2c_getack(); return sc606_i2c_getack();
} }
unsigned char sc606_i2c_inb(void) static unsigned char sc606_i2c_inb(void)
{ {
int i; int i;
unsigned char byte = 0; unsigned char byte = 0;
@ -128,6 +129,8 @@ unsigned char sc606_i2c_inb(void)
return byte; return byte;
} }
int sc606_write(unsigned char reg, unsigned char data) int sc606_write(unsigned char reg, unsigned char data)
{ {
int x = 0; int x = 0;

View file

@ -0,0 +1,35 @@
#include "kernel.h"
#include "system.h"
#include "panic.h"
#include "lcd.h"
#include <stdio.h>
const int TIMER4_MASK = 1 << 14;
int system_memory_guard(int newmode)
{
(void)newmode;
return 0;
}
extern void timer4(void);
void irq(void)
{
int intpending = INTPND;
SRCPND = intpending; /* Clear this interrupt. */
INTPND = intpending; /* Clear this interrupt. */
/* Timer 4 */
if ((intpending & TIMER4_MASK) != 0)
{
timer4();
}
else
{
/* unexpected interrupt */
}
}

View file

@ -20,33 +20,72 @@
#include <stdbool.h> #include <stdbool.h>
#include "cpu.h" #include "cpu.h"
#include "system.h" #include "system.h"
#include "kernel.h"
#define USB_RST_ASSERT GPBDAT &= ~(1 << 4)
#define USB_RST_DEASSERT GPBDAT |= (1 << 4)
#define USB_ATA_ENABLE GPBDAT |= (1 << 5)
#define USB_ATA_DISABLE GPBDAT &= ~(1 << 5)
#define USB_VPLUS_PWR_ASSERT GPBDAT |= (1 << 6)
#define USB_VPLUS_PWR_DEASSERT GPBDAT &= ~(1 << 6)
#define USB_IS_PRESENT (!(GPFDAT & 1))
/* The usb detect is one pin to the cpu active low */
inline bool usb_detect(void)
{
return USB_IS_PRESENT;
}
void usb_init_device(void) void usb_init_device(void)
{ {
USB_VPLUS_PWR_ASSERT;
sleep(HZ/20);
/* Reset the usb port */
/* Make sure the cpu pin for reset line is set to output */
GPBCON = (GPBCON & ~0x300) | 0x100;
USB_RST_ASSERT;
sleep(HZ/25);
USB_RST_DEASSERT;
/* needed to complete the reset */
USB_ATA_ENABLE;
sleep(HZ/15); /* 66ms */
USB_ATA_DISABLE;
sleep(HZ/25);
/* leave chip in low power mode */
USB_VPLUS_PWR_DEASSERT;
sleep(HZ/25);
} }
bool usb_detect(void)
{
return (GPFDAT & 1) ? false : true;
}
void usb_enable(bool on) void usb_enable(bool on)
{ {
if(on) { if (on)
int i; {
/* make sure ata_en is high */
GPBDAT &= 0x7EF; USB_VPLUS_PWR_ASSERT;
GPBCON |= 1<<8; USB_ATA_ENABLE;
GPGDAT &= 0xE7FF;
GPGDAT |= 1<<11;
for (i = 0; i < 10000000; i++) {continue;}
GPBCON &= 0x2FFCFF;
GPBDAT |= 1<<5;
GPBDAT |= 1<<6;
} else {
/* TODO how turn USB mode back off again? */
} }
else
{
/* make sure ata_en is low */
USB_ATA_DISABLE;
USB_VPLUS_PWR_DEASSERT;
}
sleep(HZ/20); // > 50ms for detecting the enable state change
} }

View file

@ -36,7 +36,6 @@
#include "file.h" #include "file.h"
#include "buffer.h" #include "buffer.h"
#include "audio.h" #include "audio.h"
#include "i2s.h"
#include "i2c.h" #include "i2c.h"
#include "i2c-meg-fx.h" #include "i2c-meg-fx.h"
/* /*
@ -54,10 +53,15 @@ int audiohw_init(void) {
/* reset I2C */ /* reset I2C */
i2c_init(); i2c_init();
/* GPC5 controls headphone output */
GPCCON &= ~(0x3 << 10);
GPCCON |= (1 << 10);
GPCDAT |= (1 << 5);
return 0; return 0;
} }
void wmcodec_write(int reg, int data) void wmcodec_write(int reg, int data)
{ {
i2c_send(0x34, (reg<<1) | ((data&0x100)>>8),data&0xff); i2c_send(0x34, (reg<<1) | ((data&0x100)>>8), data&0xff);
} }

2
tools/configure vendored
View file

@ -1031,7 +1031,7 @@ EOF
target_id=20 target_id=20
archos="gigabeatf" archos="gigabeatf"
target="-DGIGABEAT_F" target="-DGIGABEAT_F"
memory=32 # always memory=30 # always
arm9tdmicc arm9tdmicc
tool="cp" tool="cp"
bmp2rb_mono="$rootdir/tools/bmp2rb -f 0" bmp2rb_mono="$rootdir/tools/bmp2rb -f 0"