diff options
Diffstat (limited to 'firmware')
28 files changed, 1143 insertions, 189 deletions
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 | |||
136 | drivers/rtc/rtc_pcf50605.c | 136 | drivers/rtc/rtc_pcf50605.c |
137 | #elif (CONFIG_RTC == RTC_E8564) | 137 | #elif (CONFIG_RTC == RTC_E8564) |
138 | drivers/rtc/rtc_e8564.c | 138 | drivers/rtc/rtc_e8564.c |
139 | #elif (CONFIG_RTC == RTC_S3C2440) | ||
140 | drivers/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 | |||
447 | target/arm/gigabeat/meg-fx/sc606-meg-fx.c | 449 | target/arm/gigabeat/meg-fx/sc606-meg-fx.c |
448 | target/arm/gigabeat/meg-fx/usb-meg-fx.c | 450 | target/arm/gigabeat/meg-fx/usb-meg-fx.c |
449 | target/arm/gigabeat/meg-fx/wmcodec-meg-fx.c | 451 | target/arm/gigabeat/meg-fx/wmcodec-meg-fx.c |
452 | target/arm/gigabeat/meg-fx/dma_start.c | ||
453 | target/arm/gigabeat/meg-fx/system-meg-fx.c | ||
454 | target/arm/gigabeat/meg-fx/mmu-meg-fx.c | ||
455 | #ifndef BOOTLOADER | ||
456 | target/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) | |||
63 | MEMORY | 64 | MEMORY |
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) | |||
56 | void sleep(int ticks) | 56 | void 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 | ||
77 | void yield(void) | 77 | void 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 |
561 | void tick_start(unsigned int interval_in_ms) | 561 | void 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) | 576 | void 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 | */ | ||
69 | void pcm_init(void) | ||
70 | { | ||
71 | } | ||
72 | |||
73 | void pcm_play_dma_start(const void *addr, size_t size) | ||
74 | { | ||
75 | (void)addr; | ||
76 | (void)size; | ||
77 | } | ||
78 | |||
79 | void pcm_play_dma_stop(void) | ||
80 | { | ||
81 | } | ||
82 | |||
83 | void pcm_play_pause_pause(void) | ||
84 | { | ||
85 | } | ||
86 | |||
87 | void pcm_play_pause_unpause(void) | ||
88 | { | ||
89 | } | ||
90 | |||
91 | void pcm_set_frequency(unsigned int frequency) | ||
92 | { | ||
93 | (void)frequency; | ||
94 | } | ||
95 | |||
96 | size_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 |
264 | charger_input_state_type charger_input_state IDATA_ATTR; | 271 | charger_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 */ |
267 | static const unsigned short percent_to_volt_charge[11] = | 275 | static 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) | |||
86 | void system_reboot(void) { | 86 | void system_reboot(void) { |
87 | } | 87 | } |
88 | 88 | ||
89 | void system_init(void) { | 89 | void 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 */ | ||
135 | 1: | ||
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 | |||
143 | start_loc: | ||
144 | bl main | ||
126 | #endif | 145 | #endif |
127 | 146 | ||
128 | #else /* BOOTLOADER */ | 147 | #else /* BOOTLOADER */ |
@@ -201,7 +220,10 @@ prefetch_abort_handler: | |||
201 | fiq_handler: | 220 | fiq_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 | ||
206 | data_abort_handler: | 228 | data_abort_handler: |
207 | sub r0, lr, #8 | 229 | sub r0, lr, #8 |
@@ -210,9 +232,9 @@ data_abort_handler: | |||
210 | 232 | ||
211 | irq_handler: | 233 | irq_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 | ||
23 | void 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" */ | 25 | static 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; | 28 | static unsigned short __adc_read(int channel); |
29 | static 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); | 33 | void 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 */ | ||
68 | inline unsigned short adc_read(int channel) | ||
69 | { | ||
70 | return adc_readings[channel]; | ||
36 | } | 71 | } |
37 | 72 | ||
38 | unsigned 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 | */ | ||
80 | static 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 */ | ||
124 | static 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 | ||
27 | void ata_reset(void) | 27 | void 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 | ||
31 | void ata_enable(bool on) | 35 | void 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 | ||
36 | bool ata_is_coldstart(void) | 43 | bool 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 | ||
26 | int confval = SC606_LOW_FREQ; | 27 | static int confval = SC606_LOW_FREQ; |
28 | |||
29 | void __backlight_init(void) | ||
30 | { | ||
31 | } | ||
27 | 32 | ||
28 | void __backlight_on(void) | 33 | void __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 | ||
22 | void __backlight_init(void); | ||
22 | void __backlight_on(void); | 23 | void __backlight_on(void); |
23 | void __backlight_off(void); | 24 | void __backlight_off(void); |
24 | void __backlight_set_brightness(int val); | 25 | void __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 | ||
30 | static bool headphones_detect; | ||
31 | |||
32 | static 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 | |||
30 | void button_init_device(void) | 49 | void button_init_device(void) |
31 | { | 50 | { |
32 | /* Power, Remote Play & Hold switch */ | 51 | /* Power, Remote Play & Hold switch */ |
33 | } | 52 | } |
34 | 53 | ||
35 | bool button_hold(void) | 54 | |
55 | |||
56 | inline bool button_hold(void) | ||
36 | { | 57 | { |
37 | return (GPGDAT & (1 << 15)); | 58 | return (GPGDAT & (1 << 15)); |
38 | } | 59 | } |
39 | 60 | ||
40 | int 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 | ||
63 | int 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 | |||
141 | bool 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 | |||
3 | void 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 | |||
7 | extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void); | ||
8 | |||
9 | void 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 | ||
8 | void lcd_init_device(void); | 8 | void lcd_init_device(void); |
9 | void lcd_update_rec(int, int, int, int); | 9 | void lcd_update_rec(int, int, int, int); |
10 | void lcd_update(void); | 10 | void lcd_update(void); |
11 | 11 | ||
12 | bool usedmablit = false; | ||
13 | |||
12 | /* LCD init */ | 14 | /* LCD init */ |
13 | void lcd_init_device(void) | 15 | void 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. */ |
18 | void lcd_update_rect(int x, int y, int width, int height) | 23 | void 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 */ | ||
79 | void 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 | |||
168 | void lcd_set_contrast(int val) { | ||
169 | (void) val; | ||
170 | // TODO: | ||
171 | } | ||
172 | |||
173 | void lcd_set_invert_display(bool yesno) { | ||
174 | (void) yesno; | ||
175 | // TODO: | ||
176 | } | ||
177 | |||
178 | void 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 | |||
190 | void 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 */ | ||
48 | void lcd_yuv_blit(unsigned char * const src[3], | 209 | void 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 | |||
4 | void map_memory(void); | ||
5 | static void enable_mmu(void); | ||
6 | static void set_ttb(void); | ||
7 | static void set_page_tables(void); | ||
8 | static 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 | |||
16 | void map_memory(void) { | ||
17 | set_ttb(); | ||
18 | set_page_tables(); | ||
19 | enable_mmu(); | ||
20 | } | ||
21 | |||
22 | unsigned int* ttb_base; | ||
23 | const int ttb_size = 4096; | ||
24 | |||
25 | void 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 | |||
43 | void 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 | |||
53 | void 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 | |||
72 | static 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 | |||
26 | static 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 | |||
36 | unsigned short * p; | ||
37 | size_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"))); | ||
44 | void fiq(void) ICODE_ATTR __attribute__ ((interrupt ("FIQ"))); | ||
45 | void 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 | |||
81 | void 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 | |||
110 | void 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 */ | ||
182 | void 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 | |||
208 | void pcm_play_pause_pause(void) | ||
209 | { | ||
210 | /* idle */ | ||
211 | IISCON |= (1<<3); | ||
212 | } | ||
213 | |||
214 | |||
215 | |||
216 | void pcm_play_pause_unpause(void) | ||
217 | { | ||
218 | /* no idle */ | ||
219 | IISCON &= ~(1<<3); | ||
220 | } | ||
221 | |||
222 | |||
223 | |||
224 | void 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 | |||
250 | size_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 */ | ||
258 | void pcm_apply_settings(bool reset) | ||
259 | { | ||
260 | (void)reset; | ||
261 | } | ||
262 | |||
263 | void pcm_set_monitor(int monitor) | ||
264 | { | ||
265 | (void)monitor; | ||
266 | } | ||
267 | /** **/ | ||
268 | |||
269 | void 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) | ||
290 | void 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 | ||
34 | bool charger_inserted(void) | 36 | bool 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. */ | ||
42 | bool charging_state(void) { | ||
43 | return (GPGDAT & (1 << 8)) ? false : true; | ||
37 | } | 44 | } |
38 | 45 | ||
39 | void ide_power_enable(bool on) | 46 | void 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 | ||
44 | bool ide_powered(void) | 54 | bool ide_powered(void) |
45 | { | 55 | { |
46 | return true; | 56 | return (GPGDAT & (1 << 11)) != 0; |
47 | } | 57 | } |
48 | 58 | ||
49 | void power_off(void) | 59 | void 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 | ||
30 | void sc606_i2c_start(void) | 31 | static 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 | ||
39 | void sc606_i2c_restart(void) | 40 | static 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 | ||
48 | void sc606_i2c_stop(void) | 49 | static 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 | ||
58 | void sc606_i2c_ack(void) | 59 | static 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 | ||
67 | int sc606_i2c_getack(void) | 68 | static 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 | ||
86 | int sc606_i2c_outb(unsigned char byte) | 87 | static 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 | ||
109 | unsigned char sc606_i2c_inb(void) | 110 | static 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 | |||
131 | int sc606_write(unsigned char reg, unsigned char data) | 134 | int 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 | |||
8 | const int TIMER4_MASK = 1 << 14; | ||
9 | |||
10 | int system_memory_guard(int newmode) | ||
11 | { | ||
12 | (void)newmode; | ||
13 | return 0; | ||
14 | } | ||
15 | |||
16 | extern void timer4(void); | ||
17 | |||
18 | void 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 | ||
24 | void 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 | ||
28 | bool 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 */ | ||
39 | inline bool usb_detect(void) | ||
29 | { | 40 | { |
30 | return (GPFDAT & 1) ? false : true; | 41 | return USB_IS_PRESENT; |
31 | } | 42 | } |
32 | 43 | ||
33 | void 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; | 46 | void 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; | 75 | void 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) | |||
53 | int audiohw_init(void) { | 52 | int 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 | ||
60 | void wmcodec_write(int reg, int data) | 64 | void 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 | } |