summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcoen Hirschberg <marcoen@gmail.com>2006-12-29 02:49:12 +0000
committerMarcoen Hirschberg <marcoen@gmail.com>2006-12-29 02:49:12 +0000
commit295367686ec9855c4d90f68a6003e819fef8e7ab (patch)
treeb4077ffb8d2283bf199ad12a90322be77040c2fd
parent995a804defda23233ccbdd859023f4ba3ecba0bf (diff)
downloadrockbox-295367686ec9855c4d90f68a6003e819fef8e7ab.tar.gz
rockbox-295367686ec9855c4d90f68a6003e819fef8e7ab.zip
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
-rw-r--r--apps/plugins/plugin.lds7
-rw-r--r--bootloader/gigabeat.c367
-rw-r--r--firmware/SOURCES8
-rw-r--r--firmware/app.lds11
-rw-r--r--firmware/boot.lds2
-rw-r--r--firmware/export/config-gigabeat.h52
-rw-r--r--firmware/export/config.h1
-rw-r--r--firmware/kernel.c41
-rw-r--r--firmware/pcm_playback.c41
-rw-r--r--firmware/powermgmt.c11
-rw-r--r--firmware/system.c10
-rw-r--r--firmware/target/arm/crt0.S30
-rw-r--r--firmware/target/arm/gigabeat/meg-fx/adc-meg-fx.c122
-rw-r--r--firmware/target/arm/gigabeat/meg-fx/adc-target.h11
-rw-r--r--firmware/target/arm/gigabeat/meg-fx/ata-meg-fx.c9
-rw-r--r--firmware/target/arm/gigabeat/meg-fx/ata-target.h2
-rw-r--r--firmware/target/arm/gigabeat/meg-fx/backlight-meg-fx.c7
-rw-r--r--firmware/target/arm/gigabeat/meg-fx/backlight-target.h1
-rw-r--r--firmware/target/arm/gigabeat/meg-fx/button-meg-fx.c141
-rw-r--r--firmware/target/arm/gigabeat/meg-fx/button-target.h31
-rw-r--r--firmware/target/arm/gigabeat/meg-fx/dma_start.c8
-rw-r--r--firmware/target/arm/gigabeat/meg-fx/kernel-meg-fx.c25
-rw-r--r--firmware/target/arm/gigabeat/meg-fx/lcd-meg-fx.c173
-rw-r--r--firmware/target/arm/gigabeat/meg-fx/mmu-meg-fx.c84
-rw-r--r--firmware/target/arm/gigabeat/meg-fx/pcm-meg-fx.c347
-rw-r--r--firmware/target/arm/gigabeat/meg-fx/power-meg-fx.c21
-rw-r--r--firmware/target/arm/gigabeat/meg-fx/sc606-meg-fx.c23
-rw-r--r--firmware/target/arm/gigabeat/meg-fx/system-meg-fx.c35
-rw-r--r--firmware/target/arm/gigabeat/meg-fx/usb-meg-fx.c77
-rw-r--r--firmware/target/arm/gigabeat/meg-fx/wmcodec-meg-fx.c8
-rwxr-xr-xtools/configure2
31 files changed, 1509 insertions, 199 deletions
diff --git a/apps/plugins/plugin.lds b/apps/plugins/plugin.lds
index f27733a185..52a5cc32a5 100644
--- a/apps/plugins/plugin.lds
+++ b/apps/plugins/plugin.lds
@@ -36,6 +36,11 @@ OUTPUT_FORMAT(elf32-sh)
36#define DRAMORIG 0xc00000 + STUBOFFSET 36#define DRAMORIG 0xc00000 + STUBOFFSET
37#define IRAMORIG 0x407000 37#define IRAMORIG 0x407000
38#define IRAMSIZE 0x9000 38#define IRAMSIZE 0x9000
39#elif CONFIG_CPU == S3C2440
40#define DRAMORIG 0x100 + STUBOFFSET
41#define IRAMORIG DRAMORIG
42#define IRAMSIZE 4K
43#define IRAM DRAM
39#else 44#else
40#define DRAMORIG 0x09000000 + STUBOFFSET 45#define DRAMORIG 0x09000000 + STUBOFFSET
41#endif 46#endif
@@ -73,7 +78,7 @@ SECTIONS
73 .text : 78 .text :
74 { 79 {
75 *(.text*) 80 *(.text*)
76#if defined(CPU_PP) || (CONFIG_CPU==PNX0101) 81#ifdef CPU_ARM
77 *(.glue_7) 82 *(.glue_7)
78 *(.glue_7t) 83 *(.glue_7t)
79#endif 84#endif
diff --git a/bootloader/gigabeat.c b/bootloader/gigabeat.c
index c04042cead..62c31310ae 100644
--- a/bootloader/gigabeat.c
+++ b/bootloader/gigabeat.c
@@ -17,12 +17,133 @@
17#include "panic.h" 17#include "panic.h"
18#include "power.h" 18#include "power.h"
19#include "file.h" 19#include "file.h"
20#include "button-target.h"
21
22void map_memory(void);
23
24int line = 0;
20 25
21char version[] = APPSVERSION; 26char version[] = APPSVERSION;
22 27
23void go_usb_mode(void) { 28/* This section allows you to toggle bits of any memory location */
29/* Touchpad to move around the bits. Select to toggle the red bit */
30typedef struct {
31 unsigned int address;
32 char *desc;
33} memlocation_struct;
34
35/* Just add any address and descriptions here */
36/* Must finish with 0xFFFFFFFF */
37const memlocation_struct memlocations[] = {
38/* Address Description */
39{ 0x56000000, "GPACON" },
40{ 0x56000004, "GPADAT" },
41{ 0x56000010, "GPBCON" },
42{ 0x56000014, "GPBDAT" },
43{ 0x56000020, "GPCCON" },
44{ 0x56000024, "GPCDAT" },
45{ 0x56000030, "GPDCON" },
46{ 0x56000034, "GPDDAT" },
47{ 0x56000040, "GPECON" },
48{ 0x56000044, "GPEDAT" },
49{ 0x56000050, "GPFCON" },
50{ 0x56000054, "GPFDAT" },
51{ 0x56000060, "GPGCON" },
52{ 0x56000064, "GPGDAT" },
53{ 0x56000070, "GPHCON" },
54{ 0x56000074, "GPHDAT" },
55{ 0xFFFFFFFF, 0 }
56};
57
58void memdump(void)
59{
60 int i, j;
61 int current=0, bit=0;
62 char * bitval;
63 int data;
64 char tmp[40];
65
66 while(1) {
67 i = 0;
68
69 while(memlocations[i].address != 0xFFFFFFFF) {
70
71 data = *(volatile int *)memlocations[i].address;
72
73 snprintf(tmp, sizeof(tmp), "%s %s 0x%08X",
74 (i==current) ? "*" : " ",
75 memlocations[i].desc,
76 data);
77 lcd_puts(0, i*2+5, tmp);
78
79 /* print out in binary, current bit in red */
80 for (j=31; j>=0; j--) {
81 if ((bit == j) && (current == i))
82 lcd_set_foreground(LCD_RGBPACK(255,0,0));
83 lcd_puts((31-j) + ((31-j) / 8), i*2+6, (data & (1 << j)) ? "1" : "0" );
84 lcd_set_foreground(LCD_RGBPACK(0,0,0));
85 }
86
87 i++;
88 }
89
90 data = *(volatile int *)memlocations[current].address;
91 bitval = (data & (1 << bit)) ? "1" : "0";
92 snprintf(tmp, sizeof(tmp), "%s bit %ld = %s", memlocations[current].desc, bit, bitval);
93 lcd_puts(0, (i*2)+7, tmp);
94
95 lcd_update();
96
97 /* touchpad controls */
98
99 /* Up */
100 if (GPJDAT & 0x01) {
101 if (current > 0)
102 current--;
103 while(GPJDAT & 0x01);
104 }
105
106 /* Down */
107 if (GPJDAT & 0x40) {
108 if (current < (i-1))
109 current++;
110 while(GPJDAT & 0x40);
111 }
112
113 /* Left */
114 if (GPJDAT & 0x80) {
115 if (bit < 31)
116 bit++;
117 while(GPJDAT & 0x80);
118 }
119
120 /* Right */
121 if (GPJDAT & 0x1000) {
122 if (bit > 0)
123 bit--;
124 while(GPJDAT & 0x1000);
125 }
126
127 /* Centre - Toggle Bit */
128 if (GPJDAT & 0x08) {
129 data = *(volatile int *)memlocations[current].address;
130 data = data ^ (1 << bit);
131 *(volatile int *)memlocations[current].address = data;
132 while(GPJDAT & 0x08);
133 }
134
135 /* Bail out if the power button is pressed */
136 if (GPGDAT & 1) {
137 break;
138 }
139 }
140}
141
142
143static void go_usb_mode(void) {
24 /* Drop into USB mode. This does not check for disconnection. */ 144 /* Drop into USB mode. This does not check for disconnection. */
25 145
146
26 int i; 147 int i;
27 148
28 GPBDAT &= 0x7EF; 149 GPBDAT &= 0x7EF;
@@ -34,17 +155,160 @@ void go_usb_mode(void) {
34 for (i = 0; i < 10000000; i++) {continue;} 155 for (i = 0; i < 10000000; i++) {continue;}
35 156
36 GPBCON &= 0x2FFCFF; 157 GPBCON &= 0x2FFCFF;
37 GPBDAT |= 1<<5; 158 GPBDAT |= 1<<5;
38 GPBDAT |= 1<<6; 159 GPBDAT |= 1<<6;
39} 160}
40 161
162
163/* Restores a factory kernel/bootloader from a known location */
164/* Restores the FWIMG01.DAT file back in the case of a bootloader failure */
165/* The factory or "good" bootloader must be in /GBSYSTEM/FWIMG/FWIMG01.DAT.ORIG */
166/* Returns non-zero on failure */
167int restore_fwimg01dat(void)
168{
169 int orig_file = 0, dest_file = 0;
170 int size = 0, size_read;
171 char buf[256];
172 char lcd_buf[64];
173
174 orig_file = open("/GBSYSTEM/FWIMG/FWIMG01.DAT.ORIG", O_RDONLY);
175 if (orig_file < 0) {
176 /* Couldn't open source file */
177 lcd_puts(0, line++, "Couldn't open FWIMG01.DAT.ORIG for reading");
178 lcd_update();
179 return(1);
180 }
181
182 lcd_puts(0, line++, "FWIMG01.DAT.ORIG opened for reading");
183 lcd_update();
184
185 dest_file = open("/GBSYSTEM/FWIMG/FWIMG01.DAT", O_RDWR);
186 if (dest_file < 0) {
187 /* Couldn't open destination file */
188 lcd_puts(0, line++, "Couldn't open FWIMG01.DAT.ORIG for writing");
189 lcd_update();
190 close(orig_file);
191 return(2);
192 }
193
194 lcd_puts(0, line++, "FWIMG01.DAT opened for writing");
195 lcd_update();
196
197 do {
198 /* Copy in chunks */
199 size_read = read(orig_file, buf, sizeof(buf));
200 if (size_read != write(dest_file, buf, size_read)) {
201 close(orig_file);
202 close(dest_file);
203 return(3);
204 }
205 size += size_read;
206
207 } while (size_read > 0);
208
209 close(orig_file);
210 close(dest_file);
211
212 snprintf(lcd_buf, sizeof(lcd_buf), "Finished copying %ld bytes from", size);
213 lcd_puts(0, line++, lcd_buf);
214 lcd_puts(0, line++, "FWIMG01.DAT.ORIG to FWIMG01.DAT");
215
216 return(0);
217}
218
219
220int load_rockbox(const char* file_name, unsigned char* buf, int buffer_size)
221{
222 int fd;
223 int rc;
224 int len;
225 char str[256];
226 //unsigned long chksum;
227 //char model[5];
228 //unsigned long sum;
229 //int i;
230 //char str[80];
231
232 fd = open("/.rockbox/" BOOTFILE, O_RDONLY);
233 if(fd < 0)
234 {
235 fd = open("/" BOOTFILE, O_RDONLY);
236 if(fd < 0)
237 return -1;
238 }
239 fd = open(file_name, O_RDONLY);
240 if(fd < 0)
241 return -2;
242
243 len = filesize(fd);
244
245 if (len > buffer_size) {
246 snprintf(str, sizeof(str), "len: %d buf: %d", len, buffer_size);
247 lcd_puts(0, line++, str);
248 lcd_update();
249 return -6;
250 }
251
252 /*lseek(fd, FIRMWARE_OFFSET_FILE_CRC, SEEK_SET);
253
254 rc = read(fd, &chksum, 4);
255 chksum=betoh32(chksum);*/ /* Rockbox checksums are big-endian */
256 /*if(rc < 4)
257 return -2;
258
259 rc = read(fd, model, 4);
260 if(rc < 4)
261 return -3;
262
263 model[4] = 0;
264
265 snprintf(str, 80, "Model: %s", model);
266 lcd_puts(0, line++, str);
267 snprintf(str, 80, "Checksum: %x", chksum);
268 lcd_puts(0, line++, str);
269 lcd_update();
270
271 lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET);
272*/
273
274 rc = read(fd, buf, len);
275 if(rc < len) {
276 snprintf(str, sizeof(str), "len: %d rc: %d", len, rc);
277 lcd_puts(0, line++, str);
278 lcd_update();
279 return -4;
280 }
281
282 close(fd);
283
284 /*sum = MODEL_NUMBER;
285
286 for(i = 0;i < len;i++) {
287 sum += buf[i];
288 }
289
290 snprintf(str, 80, "Sum: %x", sum);
291 lcd_puts(0, line++, str);
292 lcd_update();
293
294 if(sum != chksum)
295 return -5;*/
296
297 return len;
298}
299
41void * main(void) 300void * main(void)
42{ 301{
43 int line = 0, i; 302 int i;
44 char buf[256]; 303 char buf[256];
45 struct partinfo* pinfo; 304 struct partinfo* pinfo;
46 unsigned short* identify_info; 305 unsigned short* identify_info;
47 int testfile; 306 //int testfile;
307 unsigned char* loadbuffer;
308 int buffer_size;
309 bool load_original = false;
310 int rc;
311 int(*kernel_entry)(void);
48 312
49 lcd_init(); 313 lcd_init();
50 lcd_setfont(FONT_SYSFIXED); 314 lcd_setfont(FONT_SYSFIXED);
@@ -57,7 +321,10 @@ void * main(void)
57*/ 321*/
58 322
59 lcd_puts(0, line++, "Hold MENU when booting for rescue mode."); 323 lcd_puts(0, line++, "Hold MENU when booting for rescue mode.");
324 lcd_puts(0, line++, " \"VOL+\" button to restore original kernel");
325 lcd_puts(0, line++, " \"A\" button to load original firmware");
60 lcd_update(); 326 lcd_update();
327 sleep(1*HZ);
61 328
62 /* hold MENU to enter rescue mode */ 329 /* hold MENU to enter rescue mode */
63 if (GPGDAT & 2) { 330 if (GPGDAT & 2) {
@@ -67,12 +334,44 @@ void * main(void)
67 while(1); 334 while(1);
68 } 335 }
69 336
337 sleep(5*HZ);
338
339 if(GPGDAT & 0x10) {
340 load_original = true;
341 lcd_puts(0, line++, "Loading original firmware...");
342 lcd_update();
343 }
344
70 i = ata_init(); 345 i = ata_init();
71 i = disk_mount_all(); 346 i = disk_mount_all();
72 347
73 snprintf(buf, sizeof(buf), "disk_mount_all: %d", i); 348 snprintf(buf, sizeof(buf), "disk_mount_all: %d", i);
74 lcd_puts(0, line++, buf); 349 lcd_puts(0, line++, buf);
75 350
351 /* hold VOL+ to enter rescue mode to copy old image */
352 /* needs to be after ata_init and disk_mount_all */
353 if (GPGDAT & 4) {
354
355 /* Try to restore the original kernel/bootloader if a copy is found */
356 lcd_puts(0, line++, "Restoring FWIMG01.DAT...");
357 lcd_update();
358
359 if (!restore_fwimg01dat()) {
360 lcd_puts(0, line++, "Restoring FWIMG01.DAT successful.");
361 } else {
362 lcd_puts(0, line++, "Restoring FWIMG01.DAT failed.");
363 }
364
365 lcd_puts(0, line++, "Now power cycle to boot original");
366 lcd_update();
367 while(1);
368 }
369
370 /* Memory dump mode if Vol- pressed */
371 if (GPGDAT & 8) {
372 memdump();
373 }
374
76 identify_info = ata_get_identify(); 375 identify_info = ata_get_identify();
77 376
78 for (i=0; i < 20; i++) 377 for (i=0; i < 20; i++)
@@ -96,16 +395,68 @@ void * main(void)
96 lcd_puts(0, line++, buf); 395 lcd_puts(0, line++, buf);
97 396
98 pinfo = disk_partinfo(0); 397 pinfo = disk_partinfo(0);
99 snprintf(buf, sizeof(buf), "Partition 0: 0x%02x %ld MB", 398 snprintf(buf, sizeof(buf), "Partition 0: 0x%02x %ld MB",
100 pinfo->type, pinfo->size / 2048); 399 pinfo->type, pinfo->size / 2048);
101 lcd_puts(0, line++, buf); 400 lcd_puts(0, line++, buf);
401 lcd_update();
402
403 /* Load original firmware */
404 if(load_original) {
405 loadbuffer = (unsigned char*)0x30008000;
406 buffer_size =(unsigned char*)0x31000000 - loadbuffer;
407 rc = load_rockbox("/rockbox.gigabeat", loadbuffer, buffer_size);
408 if (rc < 0) {
409 lcd_puts(0, line++, "failed to load original firmware. Loading rockbox");
410 lcd_update();
411 sleep(2*HZ);
412 goto load_rockbox;
413 }
102 414
103 testfile = open("/boottest.txt", O_WRONLY|O_CREAT|O_TRUNC); 415 snprintf(buf, sizeof(buf), "Loaded: %d", rc);
104 write(testfile, "It works!", 9); 416 lcd_puts(0, line++, buf);
105 close(testfile); 417 lcd_update();
418 sleep(2*HZ);
419
420
421 (*((int*)0x7000000)) = 333;
422 rc = *((int*)0x7000000+0x8000000);
423 snprintf(buf, sizeof(buf), "Bank0 mem test: %d", rc);
424 lcd_puts(0, line++, buf);
425 lcd_update();
426 sleep(3*HZ);
427
428 lcd_puts(0, line++, "Woops, should not return from firmware!");
429 lcd_update();
430 goto usb;
431 }
106 432
433load_rockbox:
434 map_memory();
435 lcd_puts(0, line, "Loading Rockbox...");
107 lcd_update(); 436 lcd_update();
437 sleep(HZ*4);
438
439 // TODO: read those values from somwhere
440 loadbuffer = (unsigned char*) 0x100;
441 buffer_size = (unsigned char*)0x400000 - loadbuffer;
442 rc=load_rockbox("/rockbox.gigabeat", loadbuffer, buffer_size);
443 if (rc < 0) {
444 snprintf(buf, sizeof(buf), "Rockbox error: %d",rc);
445 lcd_puts(0, line++, buf);
446 lcd_update();
447 } else {
448 lcd_puts(0, line++, "Rockbox loaded.");
449 lcd_update();
450 kernel_entry = (void*)0x100;
451 rc = kernel_entry();
452 snprintf(buf, sizeof(buf), "Woops, should not return from firmware: %d", rc);
453 lcd_puts(0, line++, buf);
454 lcd_update();
455 goto usb;
456 }
457
108 458
459usb:
109 /* now wait in USB mode so the bootloader can be updated */ 460 /* now wait in USB mode so the bootloader can be updated */
110 go_usb_mode(); 461 go_usb_mode();
111 while(1); 462 while(1);
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 6a4f172e47..4f8e531a2e 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -136,6 +136,8 @@ drivers/rtc/rtc_pcf50606.c
136drivers/rtc/rtc_pcf50605.c 136drivers/rtc/rtc_pcf50605.c
137#elif (CONFIG_RTC == RTC_E8564) 137#elif (CONFIG_RTC == RTC_E8564)
138drivers/rtc/rtc_e8564.c 138drivers/rtc/rtc_e8564.c
139#elif (CONFIG_RTC == RTC_S3C2440)
140drivers/rtc/rtc_s3c2440.c
139#endif /* (CONFIG_RTC == RTC_) */ 141#endif /* (CONFIG_RTC == RTC_) */
140#endif /* SIMULATOR */ 142#endif /* SIMULATOR */
141 143
@@ -447,6 +449,12 @@ target/arm/gigabeat/meg-fx/power-meg-fx.c
447target/arm/gigabeat/meg-fx/sc606-meg-fx.c 449target/arm/gigabeat/meg-fx/sc606-meg-fx.c
448target/arm/gigabeat/meg-fx/usb-meg-fx.c 450target/arm/gigabeat/meg-fx/usb-meg-fx.c
449target/arm/gigabeat/meg-fx/wmcodec-meg-fx.c 451target/arm/gigabeat/meg-fx/wmcodec-meg-fx.c
452target/arm/gigabeat/meg-fx/dma_start.c
453target/arm/gigabeat/meg-fx/system-meg-fx.c
454target/arm/gigabeat/meg-fx/mmu-meg-fx.c
455#ifndef BOOTLOADER
456target/arm/gigabeat/meg-fx/pcm-meg-fx.c
457#endif
450#endif /* SIMULATOR */ 458#endif /* SIMULATOR */
451#endif /* GIGABEAT_F */ 459#endif /* GIGABEAT_F */
452 460
diff --git a/firmware/app.lds b/firmware/app.lds
index 965d7950af..1053437106 100644
--- a/firmware/app.lds
+++ b/firmware/app.lds
@@ -45,9 +45,10 @@ INPUT(target/sh/crt0.o)
45#define IRAMORIG 0x400000 45#define IRAMORIG 0x400000
46#define IRAMSIZE 0x7000 46#define IRAMSIZE 0x7000
47#elif CONFIG_CPU==S3C2440 47#elif CONFIG_CPU==S3C2440
48#define DRAMORIG 0x30000000 + STUBOFFSET 48#define DRAMORIG 0x100 + STUBOFFSET
49#define IRAMORIG 0x40000000 49#define IRAMORIG DRAMORIG
50#define IRAMSIZE 4K 50#define IRAMSIZE 4K
51#define IRAM DRAM
51#else 52#else
52#define DRAMORIG 0x09000000 + STUBOFFSET 53#define DRAMORIG 0x09000000 + STUBOFFSET
53#define IRAMORIG 0x0f000000 54#define IRAMORIG 0x0f000000
@@ -63,7 +64,9 @@ INPUT(target/sh/crt0.o)
63MEMORY 64MEMORY
64{ 65{
65 DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE 66 DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
67#if CONFIG_CPU != S3C2440
66 IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE 68 IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE
69#endif
67#if CONFIG_CPU==PNX0101 70#if CONFIG_CPU==PNX0101
68 IRAM0 : ORIGIN = 0x0, LENGTH = IRAMSIZE 71 IRAM0 : ORIGIN = 0x0, LENGTH = IRAMSIZE
69#endif 72#endif
@@ -146,6 +149,8 @@ SECTIONS
146 149
147#if CONFIG_CPU==PNX0101 150#if CONFIG_CPU==PNX0101
148 .iram IRAMORIG + SIZEOF(.vectors) : 151 .iram IRAMORIG + SIZEOF(.vectors) :
152#elif CONFIG_CPU==S3C2440
153 .iram :
149#else 154#else
150 .iram IRAMORIG : 155 .iram IRAMORIG :
151#endif 156#endif
@@ -200,7 +205,7 @@ SECTIONS
200 205
201#if defined(CPU_COLDFIRE) 206#if defined(CPU_COLDFIRE)
202 .bss ADDR(.data) + SIZEOF(.data) + SIZEOF(.iram): 207 .bss ADDR(.data) + SIZEOF(.data) + SIZEOF(.iram):
203#elif defined(CPU_ARM) 208#elif defined(CPU_ARM) && CONFIG_CPU != S3C2440
204 .bss ADDR(.data) + SIZEOF(.data) + SIZEOF(.iram) + SIZEOF(.vectors): 209 .bss ADDR(.data) + SIZEOF(.data) + SIZEOF(.iram) + SIZEOF(.vectors):
205#else 210#else
206 .bss : 211 .bss :
diff --git a/firmware/boot.lds b/firmware/boot.lds
index 6c307bd4de..a8c8947f95 100644
--- a/firmware/boot.lds
+++ b/firmware/boot.lds
@@ -119,7 +119,7 @@ SECTIONS
119} 119}
120#elif (CONFIG_CPU==S3C2440) 120#elif (CONFIG_CPU==S3C2440)
121{ 121{
122 . = DRAMORIG + 0x8000; 122 . = DRAMORIG + 0x1000000;
123 .text : { 123 .text : {
124 *(.init.text) 124 *(.init.text)
125 *(.text) 125 *(.text)
diff --git a/firmware/export/config-gigabeat.h b/firmware/export/config-gigabeat.h
index ea72c348ea..b458a0eccd 100644
--- a/firmware/export/config-gigabeat.h
+++ b/firmware/export/config-gigabeat.h
@@ -14,6 +14,12 @@
14/* define this if you have a colour LCD */ 14/* define this if you have a colour LCD */
15#define HAVE_LCD_COLOR 1 15#define HAVE_LCD_COLOR 1
16 16
17/* define this if you have access to the quickscreen */
18#define HAVE_QUICKSCREEN
19
20/* define this if you have access to the pitchscreen */
21#define HAVE_PITCHSCREEN
22
17/* define this if you would like tagcache to build on this target */ 23/* define this if you would like tagcache to build on this target */
18#define HAVE_TAGCACHE 24#define HAVE_TAGCACHE
19 25
@@ -30,14 +36,24 @@
30#define CONFIG_CODEC SWCODEC 36#define CONFIG_CODEC SWCODEC
31 37
32/* define this if you have a real-time clock */ 38/* define this if you have a real-time clock */
33
34#if 0 /* TODO */
35#define CONFIG_RTC RTC_S3C2440 39#define CONFIG_RTC RTC_S3C2440
36#endif 40
41/* define this if the unit can be powered or charged via USB */
42#define HAVE_USB_POWER
37 43
38/* Define this for LCD backlight available */ 44/* Define this for LCD backlight available */
39#define CONFIG_BACKLIGHT BL_GIGABEAT /* port controlled PWM */ 45#define CONFIG_BACKLIGHT BL_GIGABEAT /* port controlled PWM */
40 46
47#define HAVE_BACKLIGHT_BRIGHTNESS
48
49/* Main LCD backlight brightness range and defaults */
50#define MIN_BRIGHTNESS_SETTING 0 /* 0.5 mA */
51#define MIN_ACTIVE_BRIGHTNESS_SETTING 16 /* lowest active brightness */
52#define MAX_DIM_BRIGHTNESS_SETTING 15 /* highest 'dimness' */
53#define MAX_BRIGHTNESS_SETTING 63 /* 32 mA */
54#define DEFAULT_BRIGHTNESS_SETTING 39 /* 20 mA */
55#define DEFAULT_DIMNESS_SETTING 9 /* 5 mA */
56
41/* Define this if you have a software controlled poweroff */ 57/* Define this if you have a software controlled poweroff */
42#define HAVE_SW_POWEROFF 58#define HAVE_SW_POWEROFF
43 59
@@ -54,23 +70,27 @@
54 70
55#ifndef SIMULATOR 71#ifndef SIMULATOR
56 72
73/* The LCD on a Gigabeat is 240x320 - it is portrait */
74#define HAVE_PORTRAIT_LCD
75
57/* Define this if you have a Motorola SCF5249 */ 76/* Define this if you have a Motorola SCF5249 */
58#define CONFIG_CPU S3C2440 77#define CONFIG_CPU S3C2440
59 78
60/* Define this if you want to use coldfire's i2c interface */ 79/* Define this if you want to use coldfire's i2c interface */
61#define CONFIG_I2C I2C_S3C2440 80#define CONFIG_I2C I2C_S3C2440
62 81
63/* Type of mobile power */ 82/* Type of mobile power - check this out */
64#define CONFIG_BATTERY BATT_LIPOL1300 83#define CONFIG_BATTERY BATT_LIION830 /* could change this later */
65#define BATTERY_CAPACITY_MIN 1300 /* min. capacity selectable */ 84#define BATTERY_CAPACITY_MIN 750 /* min. capacity selectable */
66#define BATTERY_CAPACITY_MAX 3200 /* max. capacity selectable */ 85#define BATTERY_CAPACITY_MAX 850 /* max. capacity selectable */
67#define BATTERY_CAPACITY_INC 50 /* capacity increment */ 86#define BATTERY_CAPACITY_INC 25 /* capacity increment */
68#define BATTERY_TYPES_COUNT 1 /* only one type */ 87#define BATTERY_TYPES_COUNT 1 /* only one type */
69 88
70#define BATTERY_SCALE_FACTOR 6852 /* FIX: this value is picked at random */ 89/* ADC[0] is (530) at discharge and 625 at full charge */
90#define BATTERY_SCALE_FACTOR 6450
71 91
72/* Hardware controlled charging? FIXME */ 92/* Hardware controlled charging with monitoring */
73#define CONFIG_CHARGING CHARGING_SIMPLE 93#define CONFIG_CHARGING CHARGING_MONITOR
74 94
75/* define this if the hardware can be powered off while charging */ 95/* define this if the hardware can be powered off while charging */
76#define HAVE_POWEROFF_WHILE_CHARGING 96#define HAVE_POWEROFF_WHILE_CHARGING
@@ -82,9 +102,7 @@
82#define CPU_FREQ 16934400 102#define CPU_FREQ 16934400
83 103
84/* Define this if you have ATA power-off control */ 104/* Define this if you have ATA power-off control */
85#if 0 /* TODO */
86#define HAVE_ATA_POWER_OFF 105#define HAVE_ATA_POWER_OFF
87#endif
88 106
89/* Virtual LED (icon) */ 107/* Virtual LED (icon) */
90#define CONFIG_LED LED_VIRTUAL 108#define CONFIG_LED LED_VIRTUAL
@@ -99,6 +117,7 @@
99 117
100#define USB_GIGABEAT_STYLE 118#define USB_GIGABEAT_STYLE
101 119
120#define HAVE_HEADPHONE_DETECTION
102/* Define this if you have adjustable CPU frequency */ 121/* Define this if you have adjustable CPU frequency */
103#if 0 /* TODO */ 122#if 0 /* TODO */
104#define HAVE_ADJUSTABLE_CPU_FREQ 123#define HAVE_ADJUSTABLE_CPU_FREQ
@@ -107,8 +126,5 @@
107#define BOOTFILE_EXT "gigabeat" 126#define BOOTFILE_EXT "gigabeat"
108#define BOOTFILE "rockbox." BOOTFILE_EXT 127#define BOOTFILE "rockbox." BOOTFILE_EXT
109 128
110#if 0 /* TODO */ 129
111#define HAVE_BACKLIGHT_BRIGHTNESS
112#endif
113
114#endif 130#endif
diff --git a/firmware/export/config.h b/firmware/export/config.h
index 68a4920d59..e37cc3f782 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -74,6 +74,7 @@
74#define BATT_LIPOL1300 1300 /* the type used in iRiver h1x0 models */ 74#define BATT_LIPOL1300 1300 /* the type used in iRiver h1x0 models */
75#define BATT_LPCS355385 1550 /* iriver h10 20Gb - SKC LPCS355385 */ 75#define BATT_LPCS355385 1550 /* iriver h10 20Gb - SKC LPCS355385 */
76#define BATT_BP009 820 /* iriver H10 5/6Gb - iriver BP009 */ 76#define BATT_BP009 820 /* iriver H10 5/6Gb - iriver BP009 */
77#define BATT_LIION830 830 /* Toshiba Gigabeat Fxx and Xxx series MK11-2740 */
77 78
78/* CONFIG_CHARGING */ 79/* CONFIG_CHARGING */
79#define CHARGING_SIMPLE 1 /* Simple, hardware controlled charging */ 80#define CHARGING_SIMPLE 1 /* Simple, hardware controlled charging */
diff --git a/firmware/kernel.c b/firmware/kernel.c
index 01adfcc57d..75c6604682 100644
--- a/firmware/kernel.c
+++ b/firmware/kernel.c
@@ -56,7 +56,7 @@ void kernel_init(void)
56void sleep(int ticks) 56void sleep(int ticks)
57{ 57{
58#if CONFIG_CPU == S3C2440 && defined(BOOTLOADER) 58#if CONFIG_CPU == S3C2440 && defined(BOOTLOADER)
59 int counter; 59 volatile int counter;
60 TCON &= ~(1 << 20); // stop timer 4 60 TCON &= ~(1 << 20); // stop timer 4
61 // TODO: this constant depends on dividers settings inherited from 61 // TODO: this constant depends on dividers settings inherited from
62 // firmware. Set them explicitly somwhere. 62 // firmware. Set them explicitly somwhere.
@@ -76,7 +76,7 @@ void sleep(int ticks)
76 76
77void yield(void) 77void yield(void)
78{ 78{
79#if (CONFIG_CPU == S3C2440 || defined(ELIO_TPJ1022) && defined(BOOTLOADER)) 79#if ((CONFIG_CPU == S3C2440 || defined(ELIO_TPJ1022)) && defined(BOOTLOADER))
80 /* Some targets don't like yielding in the bootloader */ 80 /* Some targets don't like yielding in the bootloader */
81#else 81#else
82 switch_thread(true, NULL); 82 switch_thread(true, NULL);
@@ -560,27 +560,34 @@ void tick_start(unsigned int interval_in_ms)
560#elif CONFIG_CPU == S3C2440 560#elif CONFIG_CPU == S3C2440
561void tick_start(unsigned int interval_in_ms) 561void tick_start(unsigned int interval_in_ms)
562{ 562{
563 unsigned long count; 563 TCON &= ~(1 << 20); // stop timer 4
564 // TODO: this constant depends on dividers settings inherited from
565 // firmware. Set them explicitly somwhere.
566 TCNTB4 = 12193 * interval_in_ms / 1000;
567 TCON |= 1 << 21; // set manual bit
568 TCON &= ~(1 << 21); // reset manual bit
569 TCON |= 1 << 22; //interval mode
570 TCON |= (1 << 20); // start timer 4
564 571
565 /* period = (n + 1) / 128 , n = tick time count (1~127)*/ 572 INTMOD &= ~(1 << 14); // timer 4 to IRQ mode
566 count = interval_in_ms / 1000 * 128 - 1; 573 INTMSK &= ~(1 << 14); // timer 4 unmask interrupts
574}
567 575
568 if(count > 127) 576void timer4(void) {
577 int i;
578 /* Run through the list of tick tasks */
579 for(i = 0; i < MAX_NUM_TICK_TASKS; i++)
569 { 580 {
570 panicf("Error! The tick interval is too long (%d ms)\n", 581 if(tick_funcs[i])
571 interval_in_ms); 582 {
572 return; 583 tick_funcs[i]();
584 }
573 } 585 }
574 586
575 /* Disable the tick */ 587 current_tick++;
576 TICNT &= ~(1<<7);
577 /* Set the count value */
578 TICNT |= count;
579 /* Start up the ticker */
580 TICNT |= (1<<7);
581 588
582 /* need interrupt handler ??? */ 589 /* following needs to be fixed. */
583 590 /*wake_up_thread();*/
584} 591}
585#endif 592#endif
586 593
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c
index 92a4c3e5c7..2bff437ef0 100644
--- a/firmware/pcm_playback.c
+++ b/firmware/pcm_playback.c
@@ -59,46 +59,9 @@ void pcm_play_pause_unpause(void);
59 59
60/** Functions that require targeted implementation **/ 60/** Functions that require targeted implementation **/
61 61
62#ifndef CPU_COLDFIRE 62#if !defined(CPU_COLDFIRE) && (CONFIG_CPU != S3C2440)
63 63
64#if (CONFIG_CPU == S3C2440) 64#if (CONFIG_CPU == PNX0101)
65
66/* TODO: Implement for Gigabeat
67 For now, just implement some dummy functions.
68*/
69void pcm_init(void)
70{
71}
72
73void pcm_play_dma_start(const void *addr, size_t size)
74{
75 (void)addr;
76 (void)size;
77}
78
79void pcm_play_dma_stop(void)
80{
81}
82
83void pcm_play_pause_pause(void)
84{
85}
86
87void pcm_play_pause_unpause(void)
88{
89}
90
91void pcm_set_frequency(unsigned int frequency)
92{
93 (void)frequency;
94}
95
96size_t pcm_get_bytes_waiting(void)
97{
98 return 0;
99}
100
101#elif (CONFIG_CPU == PNX0101)
102 65
103#define DMA_BUF_SAMPLES 0x100 66#define DMA_BUF_SAMPLES 0x100
104 67
diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c
index c4582a7302..65dd42810e 100644
--- a/firmware/powermgmt.c
+++ b/firmware/powermgmt.c
@@ -191,6 +191,8 @@ static const unsigned int battery_level_dangerous[BATTERY_TYPES_COUNT] =
191 105, 115 191 105, 115
192#elif CONFIG_BATTERY == BATT_LIPOL1300 /* iRiver H1x0: LiPolymer */ 192#elif CONFIG_BATTERY == BATT_LIPOL1300 /* iRiver H1x0: LiPolymer */
193 338 193 338
194#elif CONFIG_BATTERY == BATT_LIION830 /* Gigabeat F */
195 340
194#elif CONFIG_BATTERY == BATT_IAUDIO_X5 /* iAudio X5 */ 196#elif CONFIG_BATTERY == BATT_IAUDIO_X5 /* iAudio X5 */
195 354 197 354
196#elif CONFIG_BATTERY == BATT_LPCS355385 /* iriver H10 20GB: LiPolymer*/ 198#elif CONFIG_BATTERY == BATT_LPCS355385 /* iriver H10 20GB: LiPolymer*/
@@ -210,6 +212,8 @@ static const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
210 270, 280 212 270, 280
211#elif CONFIG_BATTERY == BATT_LIPOL1300 /* iRiver Hxxx */ 213#elif CONFIG_BATTERY == BATT_LIPOL1300 /* iRiver Hxxx */
212 299 214 299
215#elif CONFIG_BATTERY == BATT_LIION830 /* Gigabeat F */
216 338
213#elif CONFIG_BATTERY == BATT_IAUDIO_X5 /* iAudio X5 */ 217#elif CONFIG_BATTERY == BATT_IAUDIO_X5 /* iAudio X5 */
214 350 218 350
215#elif CONFIG_BATTERY == BATT_LPCS355385 /* iriver H10 20GB */ 219#elif CONFIG_BATTERY == BATT_LPCS355385 /* iriver H10 20GB */
@@ -252,6 +256,9 @@ static const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
252 /* May need recalibration. */ 256 /* May need recalibration. */
253 { 93, 108, 114, 118, 121, 125, 128, 132, 136, 142, 158 }, /* alkaline */ 257 { 93, 108, 114, 118, 121, 125, 128, 132, 136, 142, 158 }, /* alkaline */
254 { 103, 118, 121, 123, 124, 125, 126, 127, 128, 129, 135 } /* NiMH */ 258 { 103, 118, 121, 123, 124, 125, 126, 127, 128, 129, 135 } /* NiMH */
259#elif CONFIG_BATTERY == BATT_LIION830
260 /* Toshiba Gigabeat Li Ion 830mAH figured from discharge curve */
261 { 342, 358, 361, 368, 371, 374, 377, 381, 387, 390, 397 }
255#else /* NiMH */ 262#else /* NiMH */
256 /* original values were taken directly after charging, but it should show 263 /* original values were taken directly after charging, but it should show
257 100% after turning off the device for some hours, too */ 264 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] =
263#ifdef CONFIG_CHARGING 270#ifdef CONFIG_CHARGING
264charger_input_state_type charger_input_state IDATA_ATTR; 271charger_input_state_type charger_input_state IDATA_ATTR;
265 272
273
266/* voltages (centivolt) of 0%, 10%, ... 100% when charging enabled */ 274/* voltages (centivolt) of 0%, 10%, ... 100% when charging enabled */
267static const unsigned short percent_to_volt_charge[11] = 275static const unsigned short percent_to_volt_charge[11] =
268{ 276{
269#if CONFIG_BATTERY == BATT_LIPOL1300 277#if CONFIG_BATTERY == BATT_LIPOL1300
270 /* values measured over one full charging cycle */ 278 /* values measured over one full charging cycle */
271 354, 386, 393, 398, 400, 402, 404, 408, 413, 418, 423 /* LiPo */ 279 354, 386, 393, 398, 400, 402, 404, 408, 413, 418, 423 /* LiPo */
280#elif CONFIG_BATTERY == BATT_LIION830
281 /* Toshiba Gigabeat Li Ion 830mAH */
282 347, 363, 366, 373, 376, 379, 382, 386, 393, 403, 411
272#elif CONFIG_BATTERY == BATT_LPCS355385 283#elif CONFIG_BATTERY == BATT_LPCS355385
273 /* iriver H10 20GB */ 284 /* iriver H10 20GB */
274 399, 403, 406, 408, 410, 412, 415, 418, 422, 426, 431 285 399, 403, 406, 408, 410, 412, 415, 418, 422, 426, 431
diff --git a/firmware/system.c b/firmware/system.c
index 2ec9ff7a41..2bbcd06378 100644
--- a/firmware/system.c
+++ b/firmware/system.c
@@ -86,7 +86,15 @@ void cpu_idle_mode(bool on_off)
86void system_reboot(void) { 86void system_reboot(void) {
87} 87}
88 88
89void system_init(void) { 89void system_init(void)
90{
91 /* Turn off un-needed devices */
92
93 /* Turn off all of the UARTS */
94 CLKCON &= ~( (1<<10) | (1<<11) |(1<<12) );
95
96 /* Turn off AC97 and Camera */
97 CLKCON &= ~( (1<<19) | (1<<20) );
90} 98}
91 99
92#endif 100#endif
diff --git a/firmware/target/arm/crt0.S b/firmware/target/arm/crt0.S
index 82b7c31f92..c552e44320 100644
--- a/firmware/target/arm/crt0.S
+++ b/firmware/target/arm/crt0.S
@@ -122,7 +122,26 @@ start:
122/* Code for ARM bootloader targets other than iPod go here */ 122/* Code for ARM bootloader targets other than iPod go here */
123 123
124#if CONFIG_CPU == S3C2440 124#if CONFIG_CPU == S3C2440
125 bl main 125 /* get the high part of our execute address */
126 ldr r2, =0xffffff00
127 and r4, pc, r2
128
129 /* Copy bootloader to safe area - 0x31000000 */
130 mov r5, #0x30000000
131 add r5, r5, #0x1000000
132 ldr r6, = _dataend
133 sub r0, r6, r5 /* length of loader */
134 add r0, r4, r0 /* r0 points to start of loader */
1351:
136 cmp r5, r6
137 ldrcc r2, [r4], #4
138 strcc r2, [r5], #4
139 bcc 1b
140
141 ldr pc, =start_loc /* jump to the relocated start_loc: */
142
143start_loc:
144 bl main
126#endif 145#endif
127 146
128#else /* BOOTLOADER */ 147#else /* BOOTLOADER */
@@ -201,7 +220,10 @@ prefetch_abort_handler:
201fiq_handler: 220fiq_handler:
202 @ Branch straight to FIQ handler in pcm_playback.c. This also handles the 221 @ Branch straight to FIQ handler in pcm_playback.c. This also handles the
203 @ the correct return sequence. 222 @ the correct return sequence.
204 ldr pc, =fiq 223 stmfd sp!, {r0-r7, r12, lr}
224 bl fiq
225 ldmfd sp!, {r0-r7, r12, lr}
226 subs pc, lr, #4
205 227
206data_abort_handler: 228data_abort_handler:
207 sub r0, lr, #8 229 sub r0, lr, #8
@@ -210,9 +232,9 @@ data_abort_handler:
210 232
211irq_handler: 233irq_handler:
212#ifndef STUB 234#ifndef STUB
213 stmfd sp!, {r0-r3, r12, lr} 235 stmfd sp!, {r0-r11, r12, lr}
214 bl irq 236 bl irq
215 ldmfd sp!, {r0-r3, r12, lr} 237 ldmfd sp!, {r0-r11, r12, lr}
216#endif 238#endif
217 subs pc, lr, #4 239 subs pc, lr, #4
218 240
diff --git a/firmware/target/arm/gigabeat/meg-fx/adc-meg-fx.c b/firmware/target/arm/gigabeat/meg-fx/adc-meg-fx.c
index 78b9dea5b2..4c448c2e41 100644
--- a/firmware/target/arm/gigabeat/meg-fx/adc-meg-fx.c
+++ b/firmware/target/arm/gigabeat/meg-fx/adc-meg-fx.c
@@ -18,24 +18,67 @@
18 ****************************************************************************/ 18 ****************************************************************************/
19#include "cpu.h" 19#include "cpu.h"
20#include "adc-target.h" 20#include "adc-target.h"
21#include "kernel.h"
21 22
22 23
23void adc_init(void) {
24 /* Turn on the ADC PCLK */
25 CLKCON |= (1<<15);
26 24
27 /* Set channel 0, normal mode, disable "start by read" */ 25static unsigned short adc_readings[NUM_ADC_CHANNELS];
28 ADCCON &= ~(0x3F);
29 26
30 /* No start delay. Use nromal conversion mode. */ 27/* prototypes */
31 ADCDLY |= 0x1; 28static unsigned short __adc_read(int channel);
29static void adc_tick(void);
32 30
33 /* Set and enable the prescaler */ 31
34 ADCCON = (ADCCON & ~(0xff<<6)) | (0x19<<6); 32
35 ADCCON |= (1<<14); 33void adc_init(void)
34{
35 int i;
36
37 /* Turn on the ADC PCLK */
38 CLKCON |= (1<<15);
39
40 /* Set channel 0, normal mode, disable "start by read" */
41 ADCCON &= ~(0x3F);
42
43 /* No start delay. Use normal conversion mode. */
44 ADCDLY = 0x1;
45
46 /* Set and enable the prescaler */
47 ADCCON = (ADCCON & ~(0xff<<6)) | (0x19<<6);
48 ADCCON |= (1<<14);
49
50 /* prefill the adc channels */
51 for (i = 0; i < NUM_ADC_CHANNELS; i++)
52 {
53 adc_readings[i] = __adc_read(i);
54 }
55
56 /* start at zero so when the tick starts it is at zero */
57 adc_readings[0] = __adc_read(0);
58
59 /* attach the adc reading to the tick */
60 tick_add_task(adc_tick);
61
62
63}
64
65
66
67/* Called to get the recent ADC reading */
68inline unsigned short adc_read(int channel)
69{
70 return adc_readings[channel];
36} 71}
37 72
38unsigned short adc_read(int channel) { 73
74
75/**
76 * Read the ADC by polling
77 * @param channel The ADC channel to read
78 * @return 10bit reading from ADC channel or ADC_READ_ERROR if timeout
79 */
80static unsigned short __adc_read(int channel)
81{
39 int i; 82 int i;
40 83
41 /* Set the channel */ 84 /* Set the channel */
@@ -45,34 +88,57 @@ unsigned short adc_read(int channel) {
45 ADCCON |= 0x1; 88 ADCCON |= 0x1;
46 89
47 /* Wait for a low Enable_start */ 90 /* Wait for a low Enable_start */
48 i = 20000; 91 for (i = 20000;;) {
49 while(i > 0) { 92 if(0 == (ADCCON & 0x1)) {
50 if(ADCCON & 0x1) { 93 break;
51 i--;
52 } 94 }
53 else { 95 else {
54 break; 96 i--;
97 if (0 == i) {
98 /* Ran out of time */
99 return ADC_READ_ERROR;
100 }
55 } 101 }
56 } 102 }
57 if(i == 0) {
58 /* Ran out of time */
59 return(0);
60 }
61 103
62 /* Wait for high End_of_Conversion */ 104 /* Wait for high End_of_Conversion */
63 i = 20000; 105 for(i = 20000;;) {
64 while(i > 0) { 106 if(ADCCON & (1<<15)) {
65 if(ADCCON & (1<<15)) {
66 break; 107 break;
67 } 108 }
68 else { 109 else {
69 i--; 110 i--;
111 if(0 == i) {
112 /* Ran out of time */
113 return ADC_READ_ERROR;
114 }
70 } 115 }
71 } 116 }
72 if(i == 0) {
73 /* Ran out of time */
74 return(0);
75 }
76 117
77 return(ADCDAT0 & 0x3ff); 118 return (ADCDAT0 & 0x3ff);
119}
120
121
122
123/* add this to the tick so that the ADC converts are done in the background */
124static void adc_tick(void)
125{
126 static unsigned channel;
127
128 /* Check if the End Of Conversion is set */
129 if (ADCCON & (1<<15))
130 {
131 adc_readings[channel] = (ADCDAT0 & 0x3FF);
132 if (++channel >= NUM_ADC_CHANNELS)
133 {
134 channel = 0;
135 }
136
137 /* setup the next conversion and start it*/
138 ADCCON = (ADCCON & ~(0x7<<3)) | (channel<<3) | 0x01;
139 }
78} 140}
141
142
143
144
diff --git a/firmware/target/arm/gigabeat/meg-fx/adc-target.h b/firmware/target/arm/gigabeat/meg-fx/adc-target.h
index 8ea02b33e6..8d2beaf320 100644
--- a/firmware/target/arm/gigabeat/meg-fx/adc-target.h
+++ b/firmware/target/arm/gigabeat/meg-fx/adc-target.h
@@ -19,12 +19,19 @@
19#ifndef _ADC_TARGET_H_ 19#ifndef _ADC_TARGET_H_
20#define _ADC_TARGET_H_ 20#define _ADC_TARGET_H_
21 21
22#define NUM_ADC_CHANNELS 4 22/* only two channels used by the Gigabeat */
23#define NUM_ADC_CHANNELS 2
23 24
24#define ADC_BATTERY 0 25#define ADC_BATTERY 0
25#define ADC_UNKNOWN_2 1 26#define ADC_HPREMOTE 1
26#define ADC_UNKNOWN_3 2 27#define ADC_UNKNOWN_3 2
27#define ADC_UNKNOWN_4 3 28#define ADC_UNKNOWN_4 3
29#define ADC_UNKNOWN_5 4
30#define ADC_UNKNOWN_6 5
31#define ADC_UNKNOWN_7 6
32#define ADC_UNKNOWN_8 7
33
28#define ADC_UNREG_POWER ADC_BATTERY /* For compatibility */ 34#define ADC_UNREG_POWER ADC_BATTERY /* For compatibility */
35#define ADC_READ_ERROR 0xFFFF
29 36
30#endif 37#endif
diff --git a/firmware/target/arm/gigabeat/meg-fx/ata-meg-fx.c b/firmware/target/arm/gigabeat/meg-fx/ata-meg-fx.c
index 58fec1e6a3..ec0f3fe6ca 100644
--- a/firmware/target/arm/gigabeat/meg-fx/ata-meg-fx.c
+++ b/firmware/target/arm/gigabeat/meg-fx/ata-meg-fx.c
@@ -26,11 +26,18 @@
26 26
27void ata_reset(void) 27void ata_reset(void)
28{ 28{
29 GPGDAT &= ~(1 << 10);
30 sleep(1); /* > 25us */
31 GPGDAT |= (1 << 10);
32 sleep(1); /* > 2ms */
29} 33}
30 34
31void ata_enable(bool on) 35void ata_enable(bool on)
32{ 36{
33 (void)on; 37 if(on)
38 GPGDAT &= ~(1 << 12);
39 else
40 GPGDAT |= (1 << 12);
34} 41}
35 42
36bool ata_is_coldstart(void) 43bool ata_is_coldstart(void)
diff --git a/firmware/target/arm/gigabeat/meg-fx/ata-target.h b/firmware/target/arm/gigabeat/meg-fx/ata-target.h
index 1d49a1b874..95b66ab1bd 100644
--- a/firmware/target/arm/gigabeat/meg-fx/ata-target.h
+++ b/firmware/target/arm/gigabeat/meg-fx/ata-target.h
@@ -20,6 +20,8 @@
20#define ATA_TARGET_H 20#define ATA_TARGET_H
21 21
22/* Plain C read & write loops */ 22/* Plain C read & write loops */
23#define PREFER_C_READING
24#define PREFER_C_WRITING
23 25
24#define ATA_IOBASE 0x18000000 26#define ATA_IOBASE 0x18000000
25#define ATA_DATA (*((volatile unsigned short*)(ATA_IOBASE))) 27#define ATA_DATA (*((volatile unsigned short*)(ATA_IOBASE)))
diff --git a/firmware/target/arm/gigabeat/meg-fx/backlight-meg-fx.c b/firmware/target/arm/gigabeat/meg-fx/backlight-meg-fx.c
index 9abf34ccf9..ba98dba7d1 100644
--- a/firmware/target/arm/gigabeat/meg-fx/backlight-meg-fx.c
+++ b/firmware/target/arm/gigabeat/meg-fx/backlight-meg-fx.c
@@ -19,11 +19,16 @@
19#include "config.h" 19#include "config.h"
20#include "cpu.h" 20#include "cpu.h"
21#include "system.h" 21#include "system.h"
22#include "backlight-target.h"
22#include "backlight.h" 23#include "backlight.h"
23#include "lcd.h" 24#include "lcd.h"
24#include "sc606-meg-fx.h" 25#include "sc606-meg-fx.h"
25 26
26int confval = SC606_LOW_FREQ; 27static int confval = SC606_LOW_FREQ;
28
29void __backlight_init(void)
30{
31}
27 32
28void __backlight_on(void) 33void __backlight_on(void)
29{ 34{
diff --git a/firmware/target/arm/gigabeat/meg-fx/backlight-target.h b/firmware/target/arm/gigabeat/meg-fx/backlight-target.h
index 3204293131..e72e863ebc 100644
--- a/firmware/target/arm/gigabeat/meg-fx/backlight-target.h
+++ b/firmware/target/arm/gigabeat/meg-fx/backlight-target.h
@@ -19,6 +19,7 @@
19#ifndef BACKLIGHT_TARGET_H 19#ifndef BACKLIGHT_TARGET_H
20#define BACKLIGHT_TARGET_H 20#define BACKLIGHT_TARGET_H
21 21
22void __backlight_init(void);
22void __backlight_on(void); 23void __backlight_on(void);
23void __backlight_off(void); 24void __backlight_off(void);
24void __backlight_set_brightness(int val); 25void __backlight_set_brightness(int val);
diff --git a/firmware/target/arm/gigabeat/meg-fx/button-meg-fx.c b/firmware/target/arm/gigabeat/meg-fx/button-meg-fx.c
index 88a1b4de09..210febb7db 100644
--- a/firmware/target/arm/gigabeat/meg-fx/button-meg-fx.c
+++ b/firmware/target/arm/gigabeat/meg-fx/button-meg-fx.c
@@ -27,58 +27,127 @@
27#include "adc.h" 27#include "adc.h"
28#include "system.h" 28#include "system.h"
29 29
30static bool headphones_detect;
31
32static int const remote_buttons[] =
33{
34 BUTTON_NONE, /* Headphones connected - remote disconnected */
35 BUTTON_SELECT,
36 BUTTON_MENU, /* could be changed to BUTTON_A */
37 BUTTON_LEFT,
38 BUTTON_RIGHT,
39 BUTTON_UP, /* could be changed to BUTTON_VOL_UP */
40 BUTTON_DOWN, /* could be changed to BUTTON_VOL_DOWN */
41 BUTTON_NONE, /* Remote control attached - no buttons pressed */
42 BUTTON_NONE, /* Nothing in the headphone socket */
43};
44
45
46
47
48
30void button_init_device(void) 49void button_init_device(void)
31{ 50{
32 /* Power, Remote Play & Hold switch */ 51 /* Power, Remote Play & Hold switch */
33} 52}
34 53
35bool button_hold(void) 54
55
56inline bool button_hold(void)
36{ 57{
37 return (GPGDAT & (1 << 15)); 58 return (GPGDAT & (1 << 15));
38} 59}
39 60
40int button_read_device(void)
41{
42 int btn = BUTTON_NONE;
43 int touchpad = GPJDAT;
44 int buttons = GPGDAT;
45
46 /* Check for hold first */
47 if (buttons & (1 << 15))
48 return btn;
49 61
50 /* the side buttons */
51 if (buttons & (1 << 0))
52 btn |= BUTTON_POWER;
53
54 if (buttons & (1 << 1))
55 btn |= BUTTON_MENU;
56
57 if (buttons & (1 << 2))
58 btn |= BUTTON_VOL_UP;
59
60 if (buttons & (1 << 3))
61 btn |= BUTTON_VOL_DOWN;
62
63 if (buttons & (1 << 4))
64 btn |= BUTTON_A;
65 62
63int button_read_device(void)
64{
65 int btn;
66 int touchpad;
67 int buttons;
68 static int lastbutton;
69 unsigned short remote_adc;
70
71 /* Check for hold first - exit if asserted with no button pressed */
72 if (button_hold())
73 return BUTTON_NONE;
74
75 /* See header for ADC values when remote control buttons are pressed */
76 /* Only one button can be sensed at a time on the remote. */
77 /* Need to filter the remote button because the ADC is so fast */
78 remote_adc = adc_read(ADC_HPREMOTE);
79 btn = remote_buttons[(remote_adc + 64) / 128];
80 if (btn != lastbutton)
81 {
82 /* if the buttons dont agree twice in a row, then its none */
83 lastbutton = btn;
84 btn = BUTTON_NONE;
85 }
86
87 /*
88 * Code can be added that overrides the side buttons when the remote is
89 * plugged in: Check for remote_adc > 64 && remote_adc < 930 then skip
90 * reading the side and touch volume buttons, right, left, up, down, etc.
91 * but keep reading the Power and 'A'.
92 * For now, the buttons from remote and side and touch are used together.
93 */
94
95
96 /* the side buttons - Check before doing all of the work on each bit */
97 buttons = GPGDAT & 0x1F;
98 if (buttons)
99 {
100 if (buttons & (1 << 0))
101 btn |= BUTTON_POWER;
102
103 if (buttons & (1 << 1))
104 btn |= BUTTON_MENU;
105
106 if (buttons & (1 << 2))
107 btn |= BUTTON_VOL_UP;
108
109 if (buttons & (1 << 3))
110 btn |= BUTTON_VOL_DOWN;
111
112 if (buttons & (1 << 4))
113 btn |= BUTTON_A;
114 }
115
66 /* the touchpad */ 116 /* the touchpad */
67 if (touchpad & (1 << 0)) 117 touchpad = GPJDAT & 0x10C9;
68 btn |= BUTTON_UP; 118 if (touchpad)
119 {
120 if (touchpad & (1 << 0))
121 btn |= BUTTON_UP;
69 122
70 if (touchpad & (1 << 12)) 123 if (touchpad & (1 << 12))
71 btn |= BUTTON_RIGHT; 124 btn |= BUTTON_RIGHT;
72 125
73 if (touchpad & (1 << 6)) 126 if (touchpad & (1 << 6))
74 btn |= BUTTON_DOWN; 127 btn |= BUTTON_DOWN;
75 128
76 if (touchpad & (1 << 7)) 129 if (touchpad & (1 << 7))
77 btn |= BUTTON_LEFT; 130 btn |= BUTTON_LEFT;
78
79 if (touchpad & (1 << 3))
80 btn |= BUTTON_SELECT;
81 131
132 if (touchpad & (1 << 3))
133 btn |= BUTTON_SELECT;
134 }
135
82 return btn; 136 return btn;
83} 137}
84 138
139
140
141bool headphones_inserted(void)
142{
143 unsigned short remote_adc = adc_read(ADC_HPREMOTE);
144 if (remote_adc != ADC_READ_ERROR)
145 {
146 /* If there is nothing in the headphone socket, the ADC reads high */
147 if (remote_adc < 940)
148 headphones_detect = true;
149 else
150 headphones_detect = false;
151 }
152 return headphones_detect;
153}
diff --git a/firmware/target/arm/gigabeat/meg-fx/button-target.h b/firmware/target/arm/gigabeat/meg-fx/button-target.h
index 95fb72e601..ab68e8050f 100644
--- a/firmware/target/arm/gigabeat/meg-fx/button-target.h
+++ b/firmware/target/arm/gigabeat/meg-fx/button-target.h
@@ -45,6 +45,37 @@ int button_read_device(void);
45#define BUTTON_A 0x00000200 45#define BUTTON_A 0x00000200
46 46
47 47
48/* Toshiba Gigabeat specific remote button ADC values */
49/* The remote control uses ADC 1 to emulate button pushes
50 Reading (approx) Button HP plugged in? Remote plugged in?
51 0 N/A Yes No
52 125 Play/Pause Cant tell Yes
53 241 Speaker+ Cant tell Yes
54 369 Rewind Cant tell Yes
55 492 Fast Fwd Cant tell Yes
56 616 Vol + Cant tell Yes
57 742 Vol - Cant tell Yes
58 864 None Cant tell Yes
59 1023 N/A No No
60*/
61
62/*
63 Notes:
64
65 Buttons on the remote are translated into equivalent button presses just
66 as if you were pressing them on the Gigabeat itself.
67
68 We cannot tell if the hold is asserted on the remote. The Hold function on
69 the remote is to block the output of the buttons changing.
70
71 Only one button can be sensed at a time. If another is pressed, the button
72 with the lowest reading is dominant. So, if Rewind and Vol + are pressed
73 at the same time, Rewind value is the one that is read.
74*/
75
76
77
78
48#define BUTTON_MAIN (BUTTON_POWER|BUTTON_MENU|BUTTON_LEFT|BUTTON_RIGHT\ 79#define BUTTON_MAIN (BUTTON_POWER|BUTTON_MENU|BUTTON_LEFT|BUTTON_RIGHT\
49 |BUTTON_UP|BUTTON_DOWN|BUTTON_VOL_UP|BUTTON_VOL_DOWN\ 80 |BUTTON_UP|BUTTON_DOWN|BUTTON_VOL_UP|BUTTON_VOL_DOWN\
50 |BUTTON_SELECT|BUTTON_A) 81 |BUTTON_SELECT|BUTTON_A)
diff --git a/firmware/target/arm/gigabeat/meg-fx/dma_start.c b/firmware/target/arm/gigabeat/meg-fx/dma_start.c
new file mode 100644
index 0000000000..c1ab6c15cb
--- /dev/null
+++ b/firmware/target/arm/gigabeat/meg-fx/dma_start.c
@@ -0,0 +1,8 @@
1#include <sys/types.h>
2
3void dma_start(const void* addr, size_t size) {
4 (void) addr;
5 (void) size;
6 //TODO:
7}
8
diff --git a/firmware/target/arm/gigabeat/meg-fx/kernel-meg-fx.c b/firmware/target/arm/gigabeat/meg-fx/kernel-meg-fx.c
new file mode 100644
index 0000000000..9df90a2344
--- /dev/null
+++ b/firmware/target/arm/gigabeat/meg-fx/kernel-meg-fx.c
@@ -0,0 +1,25 @@
1#include "kernel.h"
2#include "thread.h"
3
4#include <stdio.h>
5#include "lcd.h"
6
7extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void);
8
9void timer4(void) {
10 int i;
11 /* Run through the list of tick tasks */
12 for(i = 0; i < MAX_NUM_TICK_TASKS; i++)
13 {
14 if(tick_funcs[i])
15 {
16 tick_funcs[i]();
17 }
18 }
19
20 current_tick++;
21
22 /* following needs to be fixed. */
23 /*wake_up_thread();*/
24}
25
diff --git a/firmware/target/arm/gigabeat/meg-fx/lcd-meg-fx.c b/firmware/target/arm/gigabeat/meg-fx/lcd-meg-fx.c
index f193f9806d..df5be43551 100644
--- a/firmware/target/arm/gigabeat/meg-fx/lcd-meg-fx.c
+++ b/firmware/target/arm/gigabeat/meg-fx/lcd-meg-fx.c
@@ -1,27 +1,56 @@
1#include "config.h" 1#include "config.h"
2#include <string.h>
2#include "cpu.h" 3#include "cpu.h"
3#include "lcd.h" 4#include "lcd.h"
4#include "kernel.h" 5#include "kernel.h"
5#include "system.h" 6#include "system.h"
6#include "string.h"
7 7
8void lcd_init_device(void); 8void lcd_init_device(void);
9void lcd_update_rec(int, int, int, int); 9void lcd_update_rec(int, int, int, int);
10void lcd_update(void); 10void lcd_update(void);
11 11
12bool usedmablit = false;
13
12/* LCD init */ 14/* LCD init */
13void lcd_init_device(void) 15void lcd_init_device(void)
14{ 16{
17 /* Switch from 555I mode to 565 mode */
18 LCDCON5 |= 1 << 11;
19
15} 20}
16 21
17/* Update a fraction of the display. */ 22/* Update a fraction of the display. */
18void lcd_update_rect(int x, int y, int width, int height) 23void lcd_update_rect(int x, int y, int width, int height)
19{ 24{
20 (void)x; 25 (void)x;
21 (void)y;
22 (void)width; 26 (void)width;
23 (void)height; 27
24 memcpy(FRAME, &lcd_framebuffer, sizeof(lcd_framebuffer)); 28 if (usedmablit)
29 {
30 /* Spin waiting for DMA to become available */
31 //while (DSTAT0 & (1<<20)) ;
32 if (DSTAT0 & (1<<20)) return;
33
34 /* set DMA dest */
35 DIDST0 = (int) FRAME + y * sizeof(fb_data) * LCD_WIDTH;
36
37 /* FRAME on AHB buf, increment */
38 DIDSTC0 = 0;
39 DCON0 = (((1<<30) | (1<<28) | (1<<27) | (1<<22) | (2<<20)) | ((height * sizeof(fb_data) * LCD_WIDTH) >> 4));
40
41 /* set DMA source and options */
42 DISRC0 = (int) &lcd_framebuffer + (y * sizeof(fb_data) * LCD_WIDTH) + 0x30000000;
43 DISRCC0 = 0x00; /* memory is on AHB bus, increment addresses */
44
45 /* Activate the channel */
46 DMASKTRIG0 = 0x2;
47 /* Start DMA */
48 DMASKTRIG0 |= 0x1;
49 }
50 else
51 {
52 memcpy((void*)FRAME, &lcd_framebuffer, sizeof(lcd_framebuffer));
53 }
25} 54}
26 55
27/* Update the display. 56/* Update the display.
@@ -45,6 +74,138 @@ void lcd_update(void)
45#define ROUNDOFFS (127*257) 74#define ROUNDOFFS (127*257)
46 75
47/* Performance function to blit a YUV bitmap directly to the LCD */ 76/* Performance function to blit a YUV bitmap directly to the LCD */
77/* For the Gigabeat - show it rotated */
78/* So the LCD_WIDTH is now the height */
79void lcd_yuv_blit(unsigned char * const src[3],
80 int src_x, int src_y, int stride,
81 int x, int y, int width, int height)
82{
83 width = (width + 1) & ~1;
84 fb_data *dst = (fb_data*)FRAME + x * LCD_WIDTH + (LCD_WIDTH - y) - 1;
85 fb_data *dst_last = dst - (height - 1);
86
87 for (;;)
88 {
89 fb_data *dst_row = dst;
90 int count = width;
91 const unsigned char *ysrc = src[0] + stride * src_y + src_x;
92 int y, u, v;
93 int red, green, blue;
94 unsigned rbits, gbits, bbits;
95
96 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
97 const unsigned char *usrc = src[1] + (stride/CSUB_X) * (src_y/CSUB_Y)
98 + (src_x/CSUB_X);
99 const unsigned char *vsrc = src[2] + (stride/CSUB_X) * (src_y/CSUB_Y)
100 + (src_x/CSUB_X);
101 int xphase = src_x % CSUB_X;
102 int rc, gc, bc;
103
104 u = *usrc++ - 128;
105 v = *vsrc++ - 128;
106 rc = RVFAC * v + ROUNDOFFS;
107 gc = GVFAC * v + GUFAC * u + ROUNDOFFS;
108 bc = BUFAC * u + ROUNDOFFS;
109
110 do
111 {
112 y = *ysrc++;
113 red = RYFAC * y + rc;
114 green = GYFAC * y + gc;
115 blue = BYFAC * y + bc;
116
117 if ((unsigned)red > (RYFAC*255+ROUNDOFFS))
118 {
119 if (red < 0)
120 red = 0;
121 else
122 red = (RYFAC*255+ROUNDOFFS);
123 }
124 if ((unsigned)green > (GYFAC*255+ROUNDOFFS))
125 {
126 if (green < 0)
127 green = 0;
128 else
129 green = (GYFAC*255+ROUNDOFFS);
130 }
131 if ((unsigned)blue > (BYFAC*255+ROUNDOFFS))
132 {
133 if (blue < 0)
134 blue = 0;
135 else
136 blue = (BYFAC*255+ROUNDOFFS);
137 }
138 rbits = ((unsigned)red) >> 16 ;
139 gbits = ((unsigned)green) >> 16 ;
140 bbits = ((unsigned)blue) >> 16 ;
141
142 *dst_row = (rbits << 11) | (gbits << 5) | bbits;
143
144 /* next pixel - since rotated, add WIDTH */
145 dst_row += LCD_WIDTH;
146
147 if (++xphase >= CSUB_X)
148 {
149 u = *usrc++ - 128;
150 v = *vsrc++ - 128;
151 rc = RVFAC * v + ROUNDOFFS;
152 gc = GVFAC * v + GUFAC * u + ROUNDOFFS;
153 bc = BUFAC * u + ROUNDOFFS;
154 xphase = 0;
155 }
156 }
157 while (--count);
158
159 if (dst == dst_last) break;
160
161 dst--;
162 src_y++;
163 }
164}
165
166
167
168void lcd_set_contrast(int val) {
169 (void) val;
170 // TODO:
171}
172
173void lcd_set_invert_display(bool yesno) {
174 (void) yesno;
175 // TODO:
176}
177
178void lcd_blit(const fb_data* data, int bx, int y, int bwidth,
179 int height, int stride)
180{
181 (void) data;
182 (void) bx;
183 (void) y;
184 (void) bwidth;
185 (void) height;
186 (void) stride;
187 //TODO:
188}
189
190void lcd_set_flip(bool yesno) {
191 (void) yesno;
192 // TODO:
193}
194
195
196
197
198
199
200
201
202
203
204
205
206
207#if 0
208/* Performance function to blit a YUV bitmap directly to the LCD */
48void lcd_yuv_blit(unsigned char * const src[3], 209void lcd_yuv_blit(unsigned char * const src[3],
49 int src_x, int src_y, int stride, 210 int src_x, int src_y, int stride,
50 int x, int y, int width, int height) 211 int x, int y, int width, int height)
@@ -129,3 +290,7 @@ void lcd_yuv_blit(unsigned char * const src[3],
129 } 290 }
130 while (dst < dst_end); 291 while (dst < dst_end);
131} 292}
293#endif
294
295
296
diff --git a/firmware/target/arm/gigabeat/meg-fx/mmu-meg-fx.c b/firmware/target/arm/gigabeat/meg-fx/mmu-meg-fx.c
new file mode 100644
index 0000000000..05b206c8ea
--- /dev/null
+++ b/firmware/target/arm/gigabeat/meg-fx/mmu-meg-fx.c
@@ -0,0 +1,84 @@
1#include <string.h>
2#include "s3c2440.h"
3
4void map_memory(void);
5static void enable_mmu(void);
6static void set_ttb(void);
7static void set_page_tables(void);
8static void map_section(unsigned int pa, unsigned int va, int mb, int cache_flags);
9
10#define SECTION_ADDRESS_MASK (-1 << 20)
11#define CACHE_ALL (1 << 3 | 1 << 2 )
12#define CACHE_NONE 0
13#define BUFFERED (1 << 2)
14#define MB (1 << 20)
15
16void map_memory(void) {
17 set_ttb();
18 set_page_tables();
19 enable_mmu();
20}
21
22unsigned int* ttb_base;
23const int ttb_size = 4096;
24
25void set_ttb() {
26 int i;
27 int* ttbPtr;
28 int domain_access;
29
30 /* must be 16Kb (0x4000) aligned */
31 ttb_base = (int*)0x31F00000;
32 for (i=0; i<ttb_size; i++,ttbPtr++)
33 ttbPtr = 0;
34 asm volatile("mcr p15, 0, %0, c2, c0, 0" : : "r" (ttb_base));
35
36 /* set domain D0 to "client" permission access */
37
38 domain_access = 3;
39 asm volatile("mcr p15, 0, %0, c3, c0, 0" : : "r" (domain_access));
40
41}
42
43void set_page_tables() {
44
45 map_section(0, 0, 0x1000, CACHE_NONE);
46
47 map_section(0x30000000, 0, 32, CACHE_NONE); /* map RAM to 0 */
48
49 map_section(0x30000000, 0, 30, CACHE_ALL); /* cache the first 30 MB or RAM */
50 map_section(0x31E00000, 0x31E00000, 1, BUFFERED); /* enable buffered writing for the framebuffer */
51}
52
53void map_section(unsigned int pa, unsigned int va, int mb, int cache_flags) {
54 unsigned int* ttbPtr;
55 int i;
56 int section_no;
57
58 section_no = va >> 20; /* sections are 1Mb size */
59 ttbPtr = ttb_base + section_no;
60 pa &= SECTION_ADDRESS_MASK; /* align to 1Mb */
61 for(i=0; i<mb; i++, pa += MB) {
62 *(ttbPtr + i) =
63 pa |
64 1 << 10 | /* superuser - r/w, user - no access */
65 0 << 5 | /* domain 0th */
66 1 << 4 | /* should be "1" */
67 cache_flags |
68 1 << 1; /* Section signature */
69 }
70}
71
72static void enable_mmu(void) {
73 asm volatile("mov r0, #0\n"
74 "mcr p15, 0, r0, c8, c7, 0\n" /* invalidate TLB */
75
76 "mcr p15, 0, r0, c7, c7,0\n" /* invalidate both icache and dcache */
77
78 "mrc p15, 0, r0, c1, c0, 0\n"
79 "orr r0, r0, #1<<0\n" /* enable mmu bit, icache and dcache */
80 "orr r0, r0, #1<<2\n" /* enable dcache */
81 "orr r0, r0, #1<<12\n" /* enable icache */
82 "mcr p15, 0, r0, c1, c0, 0" : : : "r0");
83 asm volatile("nop \n nop \n nop \n nop");
84}
diff --git a/firmware/target/arm/gigabeat/meg-fx/pcm-meg-fx.c b/firmware/target/arm/gigabeat/meg-fx/pcm-meg-fx.c
new file mode 100644
index 0000000000..a3c09c5c64
--- /dev/null
+++ b/firmware/target/arm/gigabeat/meg-fx/pcm-meg-fx.c
@@ -0,0 +1,347 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Michael Sevakis
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "system.h"
20#include "kernel.h"
21#include "logf.h"
22#include "audio.h"
23#include "wm8975.h"
24#include "file.h"
25
26static int pcm_freq = HW_SAMPR_DEFAULT; /* 44.1 is default */
27
28#define FIFO_COUNT ((IISFCON >> 6) & 0x01F)
29
30/* number of bytes in FIFO */
31#define IIS_FIFO_SIZE 64
32
33/* Setup for the DMA controller */
34#define DMA_CONTROL_SETUP ((1<<31) | (1<<29) | (1<<23) | (1<<22) | (1<<20))
35
36unsigned short * p;
37size_t p_size;
38
39
40
41/* DMA count has hit zero - no more data */
42/* Get more data from the callback and top off the FIFO */
43//void fiq(void) __attribute__ ((interrupt ("naked")));
44void fiq(void) ICODE_ATTR __attribute__ ((interrupt ("FIQ")));
45void fiq(void)
46{
47 /* clear any pending interrupt */
48 SRCPND = (1<<19);
49
50 /* Buffer empty. Try to get more. */
51 if (pcm_callback_for_more)
52 {
53 pcm_callback_for_more((unsigned char**)&p, &p_size);
54 }
55 else
56 {
57 /* callback func is missing? */
58 pcm_play_dma_stop();
59 return;
60 }
61
62 if (p_size)
63 {
64 /* set the new DMA values */
65 DCON2 = DMA_CONTROL_SETUP | (p_size >> 1);
66 DISRC2 = (int)p + 0x30000000;
67
68 /* Re-Activate the channel */
69 DMASKTRIG2 = 0x2;
70 }
71 else
72 {
73 /* No more DMA to do */
74 pcm_play_dma_stop();
75 }
76
77}
78
79
80
81void pcm_init(void)
82{
83 pcm_playing = false;
84 pcm_paused = false;
85 pcm_callback_for_more = NULL;
86
87 audiohw_init();
88 audiohw_enable_output(true);
89 audiohw_mute(true);
90
91 /* cannot use the WM8975 defaults since our clock is not the same */
92 /* the input master clock is 16.9344MHz - we can divide exact for that */
93 audiohw_set_sample_rate( (0<<6) | (0x11 << 1) | (0<<0));
94
95 /* init GPIO */
96 GPCCON = (GPCCON & ~(3<<14)) | (1<<14);
97 GPCDAT |= 1<<7;
98 GPECON |= 0x2aa;
99
100 /* Do no service DMA0 requests, yet */
101 /* clear any pending int and mask it */
102 INTMSK |= (1<<19); /* mask the interrupt */
103 SRCPND = (1<<19); /* clear any pending interrupts */
104 INTMOD |= (1<<19); /* connect to FIQ */
105
106}
107
108
109
110void pcm_play_dma_start(const void *addr, size_t size)
111{
112 //FIXME
113 //return;
114
115 int i;
116
117 /* sanity check: bad pointer or too small file */
118 if ((NULL == addr) || (size & ~1) <= IIS_FIFO_SIZE) return;
119
120 p = (unsigned short *)addr;
121 p_size = size;
122
123
124 /* Enable the IIS clock */
125 CLKCON |= (1<<17);
126
127 /* IIS interface setup and set to idle */
128 IISCON = (1<<5) | (1<<3);
129
130 /* slave, transmit mode, 16 bit samples - 384fs - use 16.9344Mhz */
131 IISMOD = (1<<9) | (1<<8) | (2<<6) | (1<<3) | (1<<2);
132
133 /* connect DMA to the FIFO and enable the FIFO */
134 IISFCON = (1<<15) | (1<<13);
135
136 /* prefill the FIFO with half words */
137 for (i=0; i < IIS_FIFO_SIZE; i+=2)
138 {
139 IISFIFO = *p++;
140 p_size -= 2;
141 }
142
143 /* set DMA dest */
144 DIDST2 = (int)&IISFIFO;
145
146 /* IIS is on the APB bus, INT when TC reaches 0, fixed dest addr */
147 DIDSTC2 = 0x03;
148
149 /* How many transfers to make - we transfer half-word at a time = 2 bytes */
150 /* DMA control: CURR_TC int, single service mode, I2SSDO int, HW trig */
151 /* no auto-reload, half-word (16bit) */
152 DCON2 = DMA_CONTROL_SETUP | (p_size / 2);
153
154 /* set DMA source and options */
155 DISRC2 = (int)p + 0x30000000;
156 DISRCC2 = 0x00; /* memory is on AHB bus, increment addresses */
157
158 /* clear pending DMA interrupt */
159 SRCPND = 1<<19;
160
161 enable_fiq(fiq);
162
163 /* unmask the DMA interrupt */
164 INTMSK &= ~(1<<19);
165
166 /* Activate the channel */
167 DMASKTRIG2 = 0x2;
168
169 /* turn off the idle */
170 IISCON &= ~(1<<3);
171
172 pcm_playing = true;
173
174 /* start the IIS */
175 IISCON |= (1<<0);
176
177}
178
179
180
181/* Disconnect the DMA and wait for the FIFO to clear */
182void pcm_play_dma_stop(void)
183{
184 pcm_playing = false;
185
186 /* mask the DMA interrupt */
187 INTMSK |= (1<<19);
188
189 /* De-Activate the channel */
190 DMASKTRIG2 = 0x4;
191
192 /* idle the IIS transmit */
193 IISCON |= (1<<3);
194
195 /* stop the IIS interface */
196 IISCON &= ~(1<<0);
197
198 /* Disconnect the IIS IIS clock */
199 CLKCON &= ~(1<<17);
200
201
202 disable_fiq();
203
204}
205
206
207
208void pcm_play_pause_pause(void)
209{
210 /* idle */
211 IISCON |= (1<<3);
212}
213
214
215
216void pcm_play_pause_unpause(void)
217{
218 /* no idle */
219 IISCON &= ~(1<<3);
220}
221
222
223
224void pcm_set_frequency(unsigned int frequency)
225{
226 int sr_ctrl;
227
228 switch(frequency)
229 {
230 case SAMPR_11:
231 sr_ctrl = 0x19 << 1;
232 break;
233 case SAMPR_22:
234 sr_ctrl = 0x1B << 1;
235 break;
236 default:
237 case SAMPR_44:
238 sr_ctrl = 0x11 << 1;
239 break;
240 case SAMPR_88:
241 sr_ctrl = 0x1F << 1;
242 break;
243 }
244 audiohw_set_sample_rate(sr_ctrl);
245 pcm_freq = frequency;
246}
247
248
249
250size_t pcm_get_bytes_waiting(void)
251{
252 return (DSTAT2 & 0xFFFFF) * 2;
253}
254
255
256
257/* dummy functions for those not actually supporting all this yet */
258void pcm_apply_settings(bool reset)
259{
260 (void)reset;
261}
262
263void pcm_set_monitor(int monitor)
264{
265 (void)monitor;
266}
267/** **/
268
269void pcm_mute(bool mute)
270{
271 audiohw_mute(mute);
272 if (mute)
273 sleep(HZ/16);
274}
275
276/*
277 * This function goes directly into the DMA buffer to calculate the left and
278 * right peak values. To avoid missing peaks it tries to look forward two full
279 * peek periods (2/HZ sec, 100% overlap), although it's always possible that
280 * the entire period will not be visible. To reduce CPU load it only looks at
281 * every third sample, and this can be reduced even further if needed (even
282 * every tenth sample would still be pretty accurate).
283 */
284
285/* Check for a peak every PEAK_STRIDE samples */
286#define PEAK_STRIDE 3
287/* Up to 1/50th of a second of audio for peak calculation */
288/* This should use NATIVE_FREQUENCY, or eventually an adjustable freq. value */
289#define PEAK_SAMPLES (44100/50)
290void pcm_calculate_peaks(int *left, int *right)
291{
292 short *addr;
293 short *end;
294 {
295 size_t samples = p_size / 4;
296 addr = p;
297
298 if (samples > PEAK_SAMPLES)
299 samples = PEAK_SAMPLES - (PEAK_STRIDE - 1);
300 else
301 samples -= MIN(PEAK_STRIDE - 1, samples);
302
303 end = &addr[samples * 2];
304 }
305
306 if (left && right) {
307 int left_peak = 0, right_peak = 0;
308
309 while (addr < end) {
310 int value;
311 if ((value = addr [0]) > left_peak)
312 left_peak = value;
313 else if (-value > left_peak)
314 left_peak = -value;
315
316 if ((value = addr [PEAK_STRIDE | 1]) > right_peak)
317 right_peak = value;
318 else if (-value > right_peak)
319 right_peak = -value;
320
321 addr = &addr[PEAK_STRIDE * 2];
322 }
323
324 *left = left_peak;
325 *right = right_peak;
326 }
327 else if (left || right) {
328 int peak_value = 0, value;
329
330 if (right)
331 addr += (PEAK_STRIDE | 1);
332
333 while (addr < end) {
334 if ((value = addr [0]) > peak_value)
335 peak_value = value;
336 else if (-value > peak_value)
337 peak_value = -value;
338
339 addr += PEAK_STRIDE * 2;
340 }
341
342 if (left)
343 *left = peak_value;
344 else
345 *right = peak_value;
346 }
347}
diff --git a/firmware/target/arm/gigabeat/meg-fx/power-meg-fx.c b/firmware/target/arm/gigabeat/meg-fx/power-meg-fx.c
index 688b44eaa6..eb2ffb5238 100644
--- a/firmware/target/arm/gigabeat/meg-fx/power-meg-fx.c
+++ b/firmware/target/arm/gigabeat/meg-fx/power-meg-fx.c
@@ -23,6 +23,8 @@
23#include "system.h" 23#include "system.h"
24#include "power.h" 24#include "power.h"
25#include "pcf50606.h" 25#include "pcf50606.h"
26#include "backlight.h"
27#include "backlight-target.h"
26 28
27#ifndef SIMULATOR 29#ifndef SIMULATOR
28 30
@@ -33,21 +35,34 @@ void power_init(void)
33 35
34bool charger_inserted(void) 36bool charger_inserted(void)
35{ 37{
36 return !(GPFDAT & (1 << 4)); 38 return (GPFDAT & (1 << 4)) ? false : true;
39}
40
41/* Returns true if the unit is charging the batteries. */
42bool charging_state(void) {
43 return (GPGDAT & (1 << 8)) ? false : true;
37} 44}
38 45
39void ide_power_enable(bool on) 46void ide_power_enable(bool on)
40{ 47{
41 (void)on; 48 if (on)
49 GPGDAT |= (1 << 11);
50 else
51 GPGDAT &= ~(1 << 11);
42} 52}
43 53
44bool ide_powered(void) 54bool ide_powered(void)
45{ 55{
46 return true; 56 return (GPGDAT & (1 << 11)) != 0;
47} 57}
48 58
49void power_off(void) 59void power_off(void)
50{ 60{
61 /* turn off backlight and wait for 1 second */
62 __backlight_off();
63 sleep(HZ/2);
64 /* set SLEEP bit to on in CLKCON to turn off */
65 CLKCON |=(1<<3);
51} 66}
52 67
53#else /* SIMULATOR */ 68#else /* SIMULATOR */
diff --git a/firmware/target/arm/gigabeat/meg-fx/sc606-meg-fx.c b/firmware/target/arm/gigabeat/meg-fx/sc606-meg-fx.c
index b0554a8260..39718a4ec6 100644
--- a/firmware/target/arm/gigabeat/meg-fx/sc606-meg-fx.c
+++ b/firmware/target/arm/gigabeat/meg-fx/sc606-meg-fx.c
@@ -24,10 +24,11 @@
24 24
25#define SCL_SDA_HI GPHDAT |= (3 << 9) 25#define SCL_SDA_HI GPHDAT |= (3 << 9)
26 26
27/* arbitrary delay loop */ 27/* The SC606 can clock at 400KHz: 2.5uS period -> 1.25uS half period */
28#define DELAY do { int _x; for(_x=0;_x<2000;_x++);} while (0) 28/* At 300Mhz - if loop takes 6 cycles @ 3.3nS each -> 1.25uS / 20nS -> 63 */
29#define DELAY do { volatile int _x; for(_x=0;_x<63;_x++);} while (0)
29 30
30void sc606_i2c_start(void) 31static void sc606_i2c_start(void)
31{ 32{
32 SCL_SDA_HI; 33 SCL_SDA_HI;
33 DELAY; 34 DELAY;
@@ -36,7 +37,7 @@ void sc606_i2c_start(void)
36 SCL_LO; 37 SCL_LO;
37} 38}
38 39
39void sc606_i2c_restart(void) 40static void sc606_i2c_restart(void)
40{ 41{
41 SCL_SDA_HI; 42 SCL_SDA_HI;
42 DELAY; 43 DELAY;
@@ -45,7 +46,7 @@ void sc606_i2c_restart(void)
45 SCL_LO; 46 SCL_LO;
46} 47}
47 48
48void sc606_i2c_stop(void) 49static void sc606_i2c_stop(void)
49{ 50{
50 SDA_LO; 51 SDA_LO;
51 DELAY; 52 DELAY;
@@ -55,7 +56,7 @@ void sc606_i2c_stop(void)
55 DELAY; 56 DELAY;
56} 57}
57 58
58void sc606_i2c_ack(void) 59static void sc606_i2c_ack(void)
59{ 60{
60 61
61 SDA_LO; 62 SDA_LO;
@@ -64,11 +65,11 @@ void sc606_i2c_ack(void)
64 SCL_LO; 65 SCL_LO;
65} 66}
66 67
67int sc606_i2c_getack(void) 68static int sc606_i2c_getack(void)
68{ 69{
69 int ret = 0; 70 int ret = 0;
70 71
71 /* Don't need a delay since this follows a data bit with a delay on the end */ 72 /* Don't need a delay since follows a data bit with a delay on the end */
72 SDA_INPUT; /* And set to input */ 73 SDA_INPUT; /* And set to input */
73 SCL_HI; 74 SCL_HI;
74 DELAY; 75 DELAY;
@@ -83,7 +84,7 @@ int sc606_i2c_getack(void)
83 return ret; 84 return ret;
84} 85}
85 86
86int sc606_i2c_outb(unsigned char byte) 87static int sc606_i2c_outb(unsigned char byte)
87{ 88{
88 int i; 89 int i;
89 90
@@ -106,7 +107,7 @@ int sc606_i2c_outb(unsigned char byte)
106 return sc606_i2c_getack(); 107 return sc606_i2c_getack();
107} 108}
108 109
109unsigned char sc606_i2c_inb(void) 110static unsigned char sc606_i2c_inb(void)
110{ 111{
111 int i; 112 int i;
112 unsigned char byte = 0; 113 unsigned char byte = 0;
@@ -128,6 +129,8 @@ unsigned char sc606_i2c_inb(void)
128 return byte; 129 return byte;
129} 130}
130 131
132
133
131int sc606_write(unsigned char reg, unsigned char data) 134int sc606_write(unsigned char reg, unsigned char data)
132{ 135{
133 int x = 0; 136 int x = 0;
diff --git a/firmware/target/arm/gigabeat/meg-fx/system-meg-fx.c b/firmware/target/arm/gigabeat/meg-fx/system-meg-fx.c
new file mode 100644
index 0000000000..d1c736e91f
--- /dev/null
+++ b/firmware/target/arm/gigabeat/meg-fx/system-meg-fx.c
@@ -0,0 +1,35 @@
1#include "kernel.h"
2#include "system.h"
3#include "panic.h"
4
5#include "lcd.h"
6#include <stdio.h>
7
8const int TIMER4_MASK = 1 << 14;
9
10int system_memory_guard(int newmode)
11{
12 (void)newmode;
13 return 0;
14}
15
16extern void timer4(void);
17
18void irq(void)
19{
20 int intpending = INTPND;
21
22 SRCPND = intpending; /* Clear this interrupt. */
23 INTPND = intpending; /* Clear this interrupt. */
24
25 /* Timer 4 */
26 if ((intpending & TIMER4_MASK) != 0)
27 {
28 timer4();
29 }
30 else
31 {
32 /* unexpected interrupt */
33 }
34}
35
diff --git a/firmware/target/arm/gigabeat/meg-fx/usb-meg-fx.c b/firmware/target/arm/gigabeat/meg-fx/usb-meg-fx.c
index 6e0f31e8c7..2415a099ba 100644
--- a/firmware/target/arm/gigabeat/meg-fx/usb-meg-fx.c
+++ b/firmware/target/arm/gigabeat/meg-fx/usb-meg-fx.c
@@ -20,33 +20,72 @@
20#include <stdbool.h> 20#include <stdbool.h>
21#include "cpu.h" 21#include "cpu.h"
22#include "system.h" 22#include "system.h"
23#include "kernel.h"
23 24
24void usb_init_device(void) 25#define USB_RST_ASSERT GPBDAT &= ~(1 << 4)
25{ 26#define USB_RST_DEASSERT GPBDAT |= (1 << 4)
26} 27
28#define USB_ATA_ENABLE GPBDAT |= (1 << 5)
29#define USB_ATA_DISABLE GPBDAT &= ~(1 << 5)
30
31#define USB_VPLUS_PWR_ASSERT GPBDAT |= (1 << 6)
32#define USB_VPLUS_PWR_DEASSERT GPBDAT &= ~(1 << 6)
27 33
28bool usb_detect(void) 34#define USB_IS_PRESENT (!(GPFDAT & 1))
35
36
37
38/* The usb detect is one pin to the cpu active low */
39inline bool usb_detect(void)
29{ 40{
30 return (GPFDAT & 1) ? false : true; 41 return USB_IS_PRESENT;
31} 42}
32 43
33void usb_enable(bool on)
34{
35 if(on) {
36 int i;
37 44
38 GPBDAT &= 0x7EF;
39 GPBCON |= 1<<8;
40 45
41 GPGDAT &= 0xE7FF; 46void usb_init_device(void)
42 GPGDAT |= 1<<11; 47{
48 USB_VPLUS_PWR_ASSERT;
49 sleep(HZ/20);
50
51 /* Reset the usb port */
52 /* Make sure the cpu pin for reset line is set to output */
53 GPBCON = (GPBCON & ~0x300) | 0x100;
54 USB_RST_ASSERT;
55 sleep(HZ/25);
56 USB_RST_DEASSERT;
57
58 /* needed to complete the reset */
59 USB_ATA_ENABLE;
60
61 sleep(HZ/15); /* 66ms */
62
63 USB_ATA_DISABLE;
64
65 sleep(HZ/25);
66
67 /* leave chip in low power mode */
68 USB_VPLUS_PWR_DEASSERT;
69
70 sleep(HZ/25);
71}
72
43 73
44 for (i = 0; i < 10000000; i++) {continue;}
45 74
46 GPBCON &= 0x2FFCFF; 75void usb_enable(bool on)
47 GPBDAT |= 1<<5; 76{
48 GPBDAT |= 1<<6; 77 if (on)
49 } else { 78 {
50 /* TODO how turn USB mode back off again? */ 79 /* make sure ata_en is high */
80 USB_VPLUS_PWR_ASSERT;
81 USB_ATA_ENABLE;
82 }
83 else
84 {
85 /* make sure ata_en is low */
86 USB_ATA_DISABLE;
87 USB_VPLUS_PWR_DEASSERT;
51 } 88 }
89
90 sleep(HZ/20); // > 50ms for detecting the enable state change
52} 91}
diff --git a/firmware/target/arm/gigabeat/meg-fx/wmcodec-meg-fx.c b/firmware/target/arm/gigabeat/meg-fx/wmcodec-meg-fx.c
index 3835ce6c05..fd023e1be0 100644
--- a/firmware/target/arm/gigabeat/meg-fx/wmcodec-meg-fx.c
+++ b/firmware/target/arm/gigabeat/meg-fx/wmcodec-meg-fx.c
@@ -36,7 +36,6 @@
36#include "file.h" 36#include "file.h"
37#include "buffer.h" 37#include "buffer.h"
38#include "audio.h" 38#include "audio.h"
39#include "i2s.h"
40#include "i2c.h" 39#include "i2c.h"
41#include "i2c-meg-fx.h" 40#include "i2c-meg-fx.h"
42/* 41/*
@@ -53,11 +52,16 @@ void i2s_reset(void)
53int audiohw_init(void) { 52int audiohw_init(void) {
54 /* reset I2C */ 53 /* reset I2C */
55 i2c_init(); 54 i2c_init();
55
56 /* GPC5 controls headphone output */
57 GPCCON &= ~(0x3 << 10);
58 GPCCON |= (1 << 10);
59 GPCDAT |= (1 << 5);
56 60
57 return 0; 61 return 0;
58} 62}
59 63
60void wmcodec_write(int reg, int data) 64void wmcodec_write(int reg, int data)
61{ 65{
62 i2c_send(0x34, (reg<<1) | ((data&0x100)>>8),data&0xff); 66 i2c_send(0x34, (reg<<1) | ((data&0x100)>>8), data&0xff);
63} 67}
diff --git a/tools/configure b/tools/configure
index 4cb1f96291..53be8eee91 100755
--- a/tools/configure
+++ b/tools/configure
@@ -1031,7 +1031,7 @@ EOF
1031 target_id=20 1031 target_id=20
1032 archos="gigabeatf" 1032 archos="gigabeatf"
1033 target="-DGIGABEAT_F" 1033 target="-DGIGABEAT_F"
1034 memory=32 # always 1034 memory=30 # always
1035 arm9tdmicc 1035 arm9tdmicc
1036 tool="cp" 1036 tool="cp"
1037 bmp2rb_mono="$rootdir/tools/bmp2rb -f 0" 1037 bmp2rb_mono="$rootdir/tools/bmp2rb -f 0"