summaryrefslogtreecommitdiff
path: root/firmware/target/arm/gigabeat
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 /firmware/target/arm/gigabeat
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
Diffstat (limited to 'firmware/target/arm/gigabeat')
-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
18 files changed, 1019 insertions, 106 deletions
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}