diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2008-05-10 18:00:11 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2008-05-10 18:00:11 +0000 |
commit | 80278e45aa79cee66596c257c5d3870765233e00 (patch) | |
tree | 3a974d996f2bcf7f176175c904cf22edf9132ac9 | |
parent | 6e812b1d2e7941ee1f3e7abdbc2a2eba601f17e3 (diff) | |
download | rockbox-80278e45aa79cee66596c257c5d3870765233e00.tar.gz rockbox-80278e45aa79cee66596c257c5d3870765233e00.zip |
Bring Gigabeat S bootloader one step close to a release version.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17442 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | bootloader/gigabeat-s.c | 329 | ||||
-rw-r--r-- | firmware/backlight.c | 49 | ||||
-rw-r--r-- | firmware/drivers/ata.c | 28 | ||||
-rw-r--r-- | firmware/drivers/button.c | 7 | ||||
-rw-r--r-- | firmware/export/ata.h | 1 | ||||
-rw-r--r-- | firmware/export/backlight.h | 1 | ||||
-rw-r--r-- | firmware/export/button.h | 1 | ||||
-rw-r--r-- | firmware/export/config-gigabeat-s.h | 22 | ||||
-rw-r--r-- | firmware/export/usb.h | 5 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/ata-target.h | 4 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c | 4 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/backlight-target.h | 8 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/button-imx31.c | 38 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/button-target.h | 7 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c | 48 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/system-imx31.c | 1 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/usb-target.h | 4 | ||||
-rw-r--r-- | firmware/usb.c | 19 |
18 files changed, 423 insertions, 153 deletions
diff --git a/bootloader/gigabeat-s.c b/bootloader/gigabeat-s.c index 30c2955c19..dfe13e4540 100644 --- a/bootloader/gigabeat-s.c +++ b/bootloader/gigabeat-s.c | |||
@@ -21,11 +21,15 @@ | |||
21 | #include <sprintf.h> | 21 | #include <sprintf.h> |
22 | #include "kernel.h" | 22 | #include "kernel.h" |
23 | #include "string.h" | 23 | #include "string.h" |
24 | #include "adc.h" | ||
25 | #include "powermgmt.h" | ||
24 | #include "ata.h" | 26 | #include "ata.h" |
25 | #include "dir.h" | 27 | #include "dir.h" |
26 | #include "disk.h" | 28 | #include "disk.h" |
27 | #include "common.h" | 29 | #include "common.h" |
30 | #include "backlight.h" | ||
28 | #include "usb.h" | 31 | #include "usb.h" |
32 | #include "button.h" | ||
29 | #include "font.h" | 33 | #include "font.h" |
30 | #include "lcd.h" | 34 | #include "lcd.h" |
31 | #include "usb-target.h" | 35 | #include "usb-target.h" |
@@ -39,11 +43,15 @@ static const char basedir[] = "/Content/0b00/00/"; | |||
39 | /* Can use memory after vector table up to 0x01f00000 */ | 43 | /* Can use memory after vector table up to 0x01f00000 */ |
40 | static char * const tarbuf = (char *)0x00000040; | 44 | static char * const tarbuf = (char *)0x00000040; |
41 | static const size_t tarbuf_size = 0x01f00000 - 0x00000040; | 45 | static const size_t tarbuf_size = 0x01f00000 - 0x00000040; |
42 | /* Queue to get notifications when in USB mode */ | 46 | /* Firmware data */ |
43 | static struct event_queue usb_wait_queue; | 47 | static void * const load_buf = 0x00000000; |
48 | static const size_t load_buf_size = 0x20000000 - 0x100000; | ||
49 | static const void * const start_addr = 0x00000000; | ||
44 | 50 | ||
45 | static void show_splash(int timeout, const char *msg) | 51 | static void show_splash(int timeout, const char *msg) |
46 | { | 52 | { |
53 | backlight_on(); | ||
54 | reset_screen(); | ||
47 | lcd_putsxy( (LCD_WIDTH - (SYSFONT_WIDTH * strlen(msg))) / 2, | 55 | lcd_putsxy( (LCD_WIDTH - (SYSFONT_WIDTH * strlen(msg))) / 2, |
48 | (LCD_HEIGHT - SYSFONT_HEIGHT) / 2, msg); | 56 | (LCD_HEIGHT - SYSFONT_HEIGHT) / 2, msg); |
49 | lcd_update(); | 57 | lcd_update(); |
@@ -51,6 +59,95 @@ static void show_splash(int timeout, const char *msg) | |||
51 | sleep(timeout); | 59 | sleep(timeout); |
52 | } | 60 | } |
53 | 61 | ||
62 | static bool pause_if_button_pressed(bool pre_usb) | ||
63 | { | ||
64 | while (1) | ||
65 | { | ||
66 | int button = button_read_device(); | ||
67 | |||
68 | if (pre_usb && !usb_plugged()) | ||
69 | return false; | ||
70 | |||
71 | /* Exit if no button or only the menu (settings reset) button */ | ||
72 | switch (button) | ||
73 | { | ||
74 | case BUTTON_MENU: | ||
75 | case BUTTON_NONE: | ||
76 | return true; | ||
77 | } | ||
78 | |||
79 | sleep(HZ/5); | ||
80 | |||
81 | /* If the disk powers off, the firmware will lock at startup */ | ||
82 | ata_spin(); | ||
83 | } | ||
84 | } | ||
85 | |||
86 | /* TODO: Handle charging while connected */ | ||
87 | static void handle_usb(void) | ||
88 | { | ||
89 | int button; | ||
90 | |||
91 | /* Check if plugged and pause to look at messages. If the cable was pulled | ||
92 | * while waiting, proceed as if it never was plugged. */ | ||
93 | if (!usb_plugged() || !pause_if_button_pressed(true)) | ||
94 | { | ||
95 | /* Bang on the controller */ | ||
96 | usb_init_device(); | ||
97 | return; | ||
98 | } | ||
99 | |||
100 | /** Enter USB mode **/ | ||
101 | |||
102 | /* We need full button and backlight handling now */ | ||
103 | backlight_init(); | ||
104 | button_init(); | ||
105 | |||
106 | /* Start the USB driver */ | ||
107 | usb_init(); | ||
108 | usb_start_monitoring(); | ||
109 | |||
110 | /* Wait for threads to connect or cable is pulled */ | ||
111 | show_splash(HZ/2, "Waiting for USB"); | ||
112 | |||
113 | while (1) | ||
114 | { | ||
115 | button = button_get_w_tmo(HZ/2); | ||
116 | |||
117 | if (button == SYS_USB_CONNECTED) | ||
118 | break; /* Hit */ | ||
119 | |||
120 | if (!usb_plugged()) | ||
121 | break; /* Cable pulled */ | ||
122 | } | ||
123 | |||
124 | if (button == SYS_USB_CONNECTED) | ||
125 | { | ||
126 | /* Got the message - wait for disconnect */ | ||
127 | show_splash(0, "Bootloader USB mode"); | ||
128 | |||
129 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
130 | |||
131 | while (1) | ||
132 | { | ||
133 | button = button_get(true); | ||
134 | if (button == SYS_USB_DISCONNECTED) | ||
135 | { | ||
136 | usb_acknowledge(SYS_USB_DISCONNECTED_ACK); | ||
137 | break; | ||
138 | } | ||
139 | } | ||
140 | } | ||
141 | |||
142 | /* Put drivers initialized for USB connection into a known state */ | ||
143 | backlight_on(); | ||
144 | usb_close(); | ||
145 | button_close(); | ||
146 | backlight_close(); | ||
147 | |||
148 | reset_screen(); | ||
149 | } | ||
150 | |||
54 | static void untar(int tar_fd) | 151 | static void untar(int tar_fd) |
55 | { | 152 | { |
56 | char header[TAR_HEADER_SIZE]; | 153 | char header[TAR_HEADER_SIZE]; |
@@ -60,13 +157,15 @@ static void untar(int tar_fd) | |||
60 | int ret; | 157 | int ret; |
61 | size_t size = filesize(tar_fd); | 158 | size_t size = filesize(tar_fd); |
62 | 159 | ||
63 | if (size > tarbuf_size) { | 160 | if (size > tarbuf_size) |
161 | { | ||
64 | printf("tar file too large"); /* Paranoid but proper */ | 162 | printf("tar file too large"); /* Paranoid but proper */ |
65 | return; | 163 | return; |
66 | } | 164 | } |
67 | 165 | ||
68 | ret = read(tar_fd, tarbuf, filesize(tar_fd)); | 166 | ret = read(tar_fd, tarbuf, filesize(tar_fd)); |
69 | if (ret < 0) { | 167 | if (ret < 0) |
168 | { | ||
70 | printf("couldn't read tar file (%d)", ret); | 169 | printf("couldn't read tar file (%d)", ret); |
71 | return; | 170 | return; |
72 | } | 171 | } |
@@ -131,153 +230,91 @@ static void untar(int tar_fd) | |||
131 | } | 230 | } |
132 | } | 231 | } |
133 | 232 | ||
134 | void main(void) | 233 | /* Look for a tar file or rockbox binary in the MTP directory */ |
234 | static void handle_untar(void) | ||
135 | { | 235 | { |
136 | char buf[MAX_PATH]; | 236 | char buf[MAX_PATH]; |
137 | char tarstring[6]; | 237 | char tarstring[6]; |
138 | char model[5]; | 238 | char model[5]; |
139 | 239 | struct dirent_uncached* entry; | |
140 | /* Flush and invalidate all caches (because vectors were written) */ | 240 | DIR_UNCACHED* dir; |
141 | invalidate_icache(); | 241 | int fd; |
142 | |||
143 | lcd_clear_display(); | ||
144 | printf("Gigabeat S Rockbox Bootloader v.00000013"); | ||
145 | system_init(); | ||
146 | kernel_init(); | ||
147 | printf("kernel init done"); | ||
148 | int rc; | 242 | int rc; |
149 | 243 | ||
150 | enable_interrupt(IRQ_FIQ_STATUS); | 244 | dir = opendir_uncached(basedir); |
151 | 245 | ||
152 | rc = ata_init(); | 246 | while ((entry = readdir_uncached(dir))) |
153 | if(rc) | ||
154 | { | 247 | { |
155 | reset_screen(); | 248 | if (*entry->d_name == '.') |
156 | error(EATA, rc); | 249 | continue; |
157 | } | ||
158 | printf("ata init done"); | ||
159 | 250 | ||
160 | disk_init(); | 251 | snprintf(buf, sizeof(buf), "%s%s", basedir, entry->d_name); |
161 | printf("disk init done"); | 252 | fd = open(buf, O_RDONLY); |
162 | 253 | ||
163 | rc = disk_mount_all(); | 254 | if (fd < 0) |
164 | if (rc<=0) | 255 | continue; |
165 | { | ||
166 | error(EDISK,rc); | ||
167 | } | ||
168 | 256 | ||
169 | /* Look for a tar file */ | 257 | /* Check whether the file is a rockbox binary. */ |
170 | struct dirent_uncached* entry; | 258 | lseek(fd, 4, SEEK_SET); |
171 | DIR_UNCACHED* dir; | 259 | rc = read(fd, model, 4); |
172 | int fd; | 260 | if (rc == 4) |
173 | dir = opendir_uncached(basedir); | ||
174 | while ((entry = readdir_uncached(dir))) | ||
175 | { | ||
176 | if (*entry->d_name != '.') | ||
177 | { | 261 | { |
178 | snprintf(buf, sizeof(buf), "%s%s", basedir, entry->d_name); | 262 | model[4] = 0; |
179 | fd = open(buf, O_RDONLY); | 263 | if (strcmp(model, "gigs") == 0) |
180 | if (fd >= 0) | ||
181 | { | 264 | { |
182 | /* Check whether the file is a rockbox binary. */ | 265 | printf("Found rockbox binary. Moving..."); |
183 | lseek(fd, 4, SEEK_SET); | ||
184 | rc = read(fd, model, 4); | ||
185 | if (rc == 4) | ||
186 | { | ||
187 | model[4] = 0; | ||
188 | if (strcmp(model, "gigs") == 0) | ||
189 | { | ||
190 | printf("Found rockbox binary. Moving..."); | ||
191 | close(fd); | ||
192 | remove("/.rockbox/rockbox.gigabeat"); | ||
193 | int ret = rename(buf, "/.rockbox/rockbox.gigabeat"); | ||
194 | printf("returned %d", ret); | ||
195 | sleep(HZ); | ||
196 | break; | ||
197 | } | ||
198 | } | ||
199 | |||
200 | /* Check whether the file is a tar file. */ | ||
201 | lseek(fd, 257, SEEK_SET); | ||
202 | rc = read(fd, tarstring, 5); | ||
203 | if (rc == 5) | ||
204 | { | ||
205 | tarstring[5] = 0; | ||
206 | if (strcmp(tarstring, "ustar") == 0) | ||
207 | { | ||
208 | printf("Found tar file. Unarchiving..."); | ||
209 | lseek(fd, 0, SEEK_SET); | ||
210 | untar(fd); | ||
211 | close(fd); | ||
212 | printf("Removing tar file"); | ||
213 | remove(buf); | ||
214 | break; | ||
215 | } | ||
216 | } | ||
217 | close(fd); | 266 | close(fd); |
267 | remove("/.rockbox/rockbox.gigabeat"); | ||
268 | int ret = rename(buf, "/.rockbox/rockbox.gigabeat"); | ||
269 | printf("returned %d", ret); | ||
270 | sleep(HZ); | ||
271 | break; | ||
218 | } | 272 | } |
219 | } | 273 | } |
220 | } | ||
221 | |||
222 | if (usb_plugged()) | ||
223 | { | ||
224 | /* Enter USB mode */ | ||
225 | struct queue_event ev; | ||
226 | queue_init(&usb_wait_queue, true); | ||
227 | |||
228 | /* Start the USB driver */ | ||
229 | usb_init(); | ||
230 | usb_start_monitoring(); | ||
231 | |||
232 | /* Wait for threads to connect or cable is pulled */ | ||
233 | reset_screen(); | ||
234 | show_splash(0, "Waiting for USB"); | ||
235 | |||
236 | while (1) | ||
237 | { | ||
238 | queue_wait_w_tmo(&usb_wait_queue, &ev, HZ/2); | ||
239 | |||
240 | if (ev.id == SYS_USB_CONNECTED) | ||
241 | break; /* Hit */ | ||
242 | |||
243 | if (!usb_plugged()) | ||
244 | break; /* Cable pulled */ | ||
245 | } | ||
246 | 274 | ||
247 | if (ev.id == SYS_USB_CONNECTED) | 275 | /* Check whether the file is a tar file. */ |
276 | lseek(fd, 257, SEEK_SET); | ||
277 | rc = read(fd, tarstring, 5); | ||
278 | if (rc == 5) | ||
248 | { | 279 | { |
249 | /* Got the message - wait for disconnect */ | 280 | tarstring[5] = 0; |
250 | reset_screen(); | 281 | if (strcmp(tarstring, "ustar") == 0) |
251 | show_splash(0, "Bootloader USB mode"); | 282 | { |
252 | 283 | printf("Found tar file. Unarchiving..."); | |
253 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | 284 | lseek(fd, 0, SEEK_SET); |
254 | usb_wait_for_disconnect(&usb_wait_queue); | 285 | untar(fd); |
286 | close(fd); | ||
287 | printf("Removing tar file"); | ||
288 | remove(buf); | ||
289 | break; | ||
290 | } | ||
255 | } | 291 | } |
256 | 292 | ||
257 | /* No more monitoring */ | 293 | close(fd); |
258 | usb_stop_monitoring(); | ||
259 | |||
260 | reset_screen(); | ||
261 | } | ||
262 | else | ||
263 | { | ||
264 | /* Bang on the controller */ | ||
265 | usb_init_device(); | ||
266 | } | 294 | } |
295 | } | ||
267 | 296 | ||
268 | unsigned char *loadbuffer = (unsigned char *)0x0; | 297 | /* Try to load the firmware and run it */ |
269 | int buffer_size = 31*1024*1024; | 298 | static void __attribute__((noreturn)) handle_firmware_load(void) |
299 | { | ||
300 | int rc = load_firmware(load_buf, "/.rockbox/rockbox.gigabeat", | ||
301 | load_buf_size); | ||
270 | 302 | ||
271 | rc = load_firmware(loadbuffer, "/.rockbox/rockbox.gigabeat", buffer_size); | ||
272 | if(rc < 0) | 303 | if(rc < 0) |
273 | error(EBOOTFILE, rc); | 304 | error(EBOOTFILE, rc); |
274 | 305 | ||
306 | /* Pause to look at messages */ | ||
307 | pause_if_button_pressed(false); | ||
308 | |||
309 | /* Put drivers into a known state */ | ||
310 | button_close_device(); | ||
311 | ata_close(); | ||
275 | system_prepare_fw_start(); | 312 | system_prepare_fw_start(); |
276 | 313 | ||
277 | if (rc == EOK) | 314 | if (rc == EOK) |
278 | { | 315 | { |
279 | invalidate_icache(); | 316 | invalidate_icache(); |
280 | asm volatile ("bx %0": : "r"(loadbuffer)); | 317 | asm volatile ("bx %0": : "r"(start_addr)); |
281 | } | 318 | } |
282 | 319 | ||
283 | /* Halt */ | 320 | /* Halt */ |
@@ -285,3 +322,55 @@ void main(void) | |||
285 | core_idle(); | 322 | core_idle(); |
286 | } | 323 | } |
287 | 324 | ||
325 | static void check_battery(void) | ||
326 | { | ||
327 | int batt = battery_adc_voltage(); | ||
328 | printf("Battery: %d.%03d V", batt / 1000, batt % 1000); | ||
329 | /* TODO: warn on low battery or shut down */ | ||
330 | } | ||
331 | |||
332 | void main(void) | ||
333 | { | ||
334 | int rc; | ||
335 | |||
336 | /* Flush and invalidate all caches (because vectors were written) */ | ||
337 | invalidate_icache(); | ||
338 | |||
339 | lcd_clear_display(); | ||
340 | printf("Gigabeat S Rockbox Bootloader"); | ||
341 | printf("Version %s", version); | ||
342 | system_init(); | ||
343 | kernel_init(); | ||
344 | |||
345 | enable_interrupt(IRQ_FIQ_STATUS); | ||
346 | |||
347 | /* Initialize KPP so we can poll the button states */ | ||
348 | button_init_device(); | ||
349 | |||
350 | adc_init(); | ||
351 | |||
352 | check_battery(); | ||
353 | |||
354 | rc = ata_init(); | ||
355 | if(rc) | ||
356 | { | ||
357 | reset_screen(); | ||
358 | error(EATA, rc); | ||
359 | } | ||
360 | |||
361 | disk_init(); | ||
362 | |||
363 | rc = disk_mount_all(); | ||
364 | if (rc<=0) | ||
365 | { | ||
366 | error(EDISK,rc); | ||
367 | } | ||
368 | |||
369 | printf("Init complete"); | ||
370 | |||
371 | /* Do USB first since a tar or binary could be added to the MTP directory | ||
372 | * at the time and we can untar or move after unplugging. */ | ||
373 | handle_usb(); | ||
374 | handle_untar(); | ||
375 | handle_firmware_load(); /* No return */ | ||
376 | } | ||
diff --git a/firmware/backlight.c b/firmware/backlight.c index 4a00f86f39..74cdee1205 100644 --- a/firmware/backlight.c +++ b/firmware/backlight.c | |||
@@ -39,6 +39,11 @@ | |||
39 | #include "backlight-target.h" | 39 | #include "backlight-target.h" |
40 | #endif | 40 | #endif |
41 | 41 | ||
42 | #if !defined(BOOTLOADER) | ||
43 | /* The whole driver should be built */ | ||
44 | #define BACKLIGHT_FULL_INIT | ||
45 | #endif | ||
46 | |||
42 | #ifdef SIMULATOR | 47 | #ifdef SIMULATOR |
43 | /* TODO: find a better way to do it but we need a kernel thread somewhere to | 48 | /* TODO: find a better way to do it but we need a kernel thread somewhere to |
44 | handle this */ | 49 | handle this */ |
@@ -85,7 +90,7 @@ static inline void _remote_backlight_off(void) | |||
85 | 90 | ||
86 | #endif /* SIMULATOR */ | 91 | #endif /* SIMULATOR */ |
87 | 92 | ||
88 | #if defined(HAVE_BACKLIGHT) && !defined(BOOTLOADER) | 93 | #if defined(HAVE_BACKLIGHT) && defined(BACKLIGHT_FULL_INIT) |
89 | 94 | ||
90 | enum { | 95 | enum { |
91 | BACKLIGHT_ON, | 96 | BACKLIGHT_ON, |
@@ -104,12 +109,18 @@ enum { | |||
104 | BUTTON_LIGHT_ON, | 109 | BUTTON_LIGHT_ON, |
105 | BUTTON_LIGHT_OFF, | 110 | BUTTON_LIGHT_OFF, |
106 | #endif | 111 | #endif |
112 | #ifdef BACKLIGHT_DRIVER_CLOSE | ||
113 | BACKLIGHT_QUIT, | ||
114 | #endif | ||
107 | }; | 115 | }; |
108 | 116 | ||
109 | static void backlight_thread(void); | 117 | static void backlight_thread(void); |
110 | static long backlight_stack[DEFAULT_STACK_SIZE/sizeof(long)]; | 118 | static long backlight_stack[DEFAULT_STACK_SIZE/sizeof(long)]; |
111 | static const char backlight_thread_name[] = "backlight"; | 119 | static const char backlight_thread_name[] = "backlight"; |
112 | static struct event_queue backlight_queue; | 120 | static struct event_queue backlight_queue; |
121 | #ifdef BACKLIGHT_DRIVER_CLOSE | ||
122 | static struct thread_entry *backlight_thread_p = NULL; | ||
123 | #endif | ||
113 | 124 | ||
114 | static int backlight_timer SHAREDBSS_ATTR; | 125 | static int backlight_timer SHAREDBSS_ATTR; |
115 | static int backlight_timeout SHAREDBSS_ATTR; | 126 | static int backlight_timeout SHAREDBSS_ATTR; |
@@ -158,7 +169,7 @@ void buttonlight_set_timeout(int value) | |||
158 | buttonlight_update_state(); | 169 | buttonlight_update_state(); |
159 | } | 170 | } |
160 | 171 | ||
161 | #endif | 172 | #endif /* HAVE_BUTTON_LIGHT */ |
162 | 173 | ||
163 | #ifdef HAVE_REMOTE_LCD | 174 | #ifdef HAVE_REMOTE_LCD |
164 | static int remote_backlight_timer; | 175 | static int remote_backlight_timer; |
@@ -170,7 +181,7 @@ static int remote_backlight_timeout_plugged = 5*HZ; | |||
170 | #ifdef HAS_REMOTE_BUTTON_HOLD | 181 | #ifdef HAS_REMOTE_BUTTON_HOLD |
171 | static int remote_backlight_on_button_hold = 0; | 182 | static int remote_backlight_on_button_hold = 0; |
172 | #endif | 183 | #endif |
173 | #endif | 184 | #endif /* HAVE_REMOTE_LCD */ |
174 | 185 | ||
175 | #ifdef HAVE_LCD_SLEEP | 186 | #ifdef HAVE_LCD_SLEEP |
176 | const signed char lcd_sleep_timeout_value[10] = | 187 | const signed char lcd_sleep_timeout_value[10] = |
@@ -494,6 +505,12 @@ void backlight_thread(void) | |||
494 | case SYS_USB_DISCONNECTED: | 505 | case SYS_USB_DISCONNECTED: |
495 | usb_acknowledge(SYS_USB_DISCONNECTED_ACK); | 506 | usb_acknowledge(SYS_USB_DISCONNECTED_ACK); |
496 | break; | 507 | break; |
508 | |||
509 | #ifdef BACKLIGHT_DRIVER_CLOSE | ||
510 | /* Get out of here */ | ||
511 | case BACKLIGHT_QUIT: | ||
512 | return; | ||
513 | #endif | ||
497 | } | 514 | } |
498 | if (locked) | 515 | if (locked) |
499 | continue; | 516 | continue; |
@@ -613,7 +630,9 @@ void backlight_init(void) | |||
613 | /* Leave all lights as set by the bootloader here. The settings load will | 630 | /* Leave all lights as set by the bootloader here. The settings load will |
614 | * call the appropriate backlight_set_*() functions, only changing light | 631 | * call the appropriate backlight_set_*() functions, only changing light |
615 | * status if necessary. */ | 632 | * status if necessary. */ |
616 | 633 | #ifdef BACKLIGHT_DRIVER_CLOSE | |
634 | backlight_thread_p = | ||
635 | #endif | ||
617 | create_thread(backlight_thread, backlight_stack, | 636 | create_thread(backlight_thread, backlight_stack, |
618 | sizeof(backlight_stack), 0, backlight_thread_name | 637 | sizeof(backlight_stack), 0, backlight_thread_name |
619 | IF_PRIO(, PRIORITY_USER_INTERFACE) | 638 | IF_PRIO(, PRIORITY_USER_INTERFACE) |
@@ -621,6 +640,22 @@ void backlight_init(void) | |||
621 | tick_add_task(backlight_tick); | 640 | tick_add_task(backlight_tick); |
622 | } | 641 | } |
623 | 642 | ||
643 | #ifdef BACKLIGHT_DRIVER_CLOSE | ||
644 | void backlight_close(void) | ||
645 | { | ||
646 | struct thread_entry *thread = backlight_thread_p; | ||
647 | |||
648 | /* Wait for thread to exit */ | ||
649 | if (thread == NULL) | ||
650 | return; | ||
651 | |||
652 | backlight_thread_p = NULL; | ||
653 | |||
654 | queue_post(&backlight_queue, BACKLIGHT_QUIT, 0); | ||
655 | thread_wait(thread); | ||
656 | } | ||
657 | #endif /* BACKLIGHT_DRIVER_CLOSE */ | ||
658 | |||
624 | void backlight_on(void) | 659 | void backlight_on(void) |
625 | { | 660 | { |
626 | queue_remove_from_head(&backlight_queue, BACKLIGHT_ON); | 661 | queue_remove_from_head(&backlight_queue, BACKLIGHT_ON); |
@@ -788,10 +823,10 @@ void buttonlight_set_brightness(int val) | |||
788 | } | 823 | } |
789 | #endif /* HAVE_BUTTONLIGHT_BRIGHTNESS */ | 824 | #endif /* HAVE_BUTTONLIGHT_BRIGHTNESS */ |
790 | 825 | ||
791 | #else /* !defined(HAVE_BACKLIGHT) || defined(BOOTLOADER) | 826 | #else /* !defined(HAVE_BACKLIGHT) || !defined(BACKLIGHT_FULL_INIT) |
792 | -- no backlight, empty dummy functions */ | 827 | -- no backlight, empty dummy functions */ |
793 | 828 | ||
794 | #if defined(BOOTLOADER) && defined(HAVE_BACKLIGHT) | 829 | #if defined(HAVE_BACKLIGHT) && !defined(BACKLIGHT_FULL_INIT) |
795 | void backlight_init(void) | 830 | void backlight_init(void) |
796 | { | 831 | { |
797 | (void)_backlight_init(); | 832 | (void)_backlight_init(); |
@@ -826,4 +861,4 @@ void backlight_set_brightness(int val) { (void)val; } | |||
826 | #ifdef HAVE_BUTTONLIGHT_BRIGHTNESS | 861 | #ifdef HAVE_BUTTONLIGHT_BRIGHTNESS |
827 | void buttonlight_set_brightness(int val) { (void)val; } | 862 | void buttonlight_set_brightness(int val) { (void)val; } |
828 | #endif | 863 | #endif |
829 | #endif /* defined(HAVE_BACKLIGHT) && !defined(BOOTLOADER) */ | 864 | #endif /* defined(HAVE_BACKLIGHT) && defined(BACKLIGHT_FULL_INIT) */ |
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c index 2dca17512e..87dacc3ed0 100644 --- a/firmware/drivers/ata.c +++ b/firmware/drivers/ata.c | |||
@@ -59,6 +59,7 @@ | |||
59 | #define CMD_SECURITY_FREEZE_LOCK 0xF5 | 59 | #define CMD_SECURITY_FREEZE_LOCK 0xF5 |
60 | 60 | ||
61 | #define Q_SLEEP 0 | 61 | #define Q_SLEEP 0 |
62 | #define Q_CLOSE 1 | ||
62 | 63 | ||
63 | #define READ_TIMEOUT 5*HZ | 64 | #define READ_TIMEOUT 5*HZ |
64 | 65 | ||
@@ -66,6 +67,10 @@ | |||
66 | #define ATA_POWER_OFF_TIMEOUT 2*HZ | 67 | #define ATA_POWER_OFF_TIMEOUT 2*HZ |
67 | #endif | 68 | #endif |
68 | 69 | ||
70 | #ifdef ATA_DRIVER_CLOSE | ||
71 | static struct thread_entry *ata_thread_p = NULL; | ||
72 | #endif | ||
73 | |||
69 | #if defined(MAX_PHYS_SECTOR_SIZE) && MEM == 64 | 74 | #if defined(MAX_PHYS_SECTOR_SIZE) && MEM == 64 |
70 | /* Hack - what's the deal with 5g? */ | 75 | /* Hack - what's the deal with 5g? */ |
71 | struct ata_lock | 76 | struct ata_lock |
@@ -941,6 +946,11 @@ static void ata_thread(void) | |||
941 | call_ata_idle_notifys(false); | 946 | call_ata_idle_notifys(false); |
942 | last_disk_activity = current_tick - sleep_timeout + (HZ/2); | 947 | last_disk_activity = current_tick - sleep_timeout + (HZ/2); |
943 | break; | 948 | break; |
949 | |||
950 | #ifdef ATA_DRIVER_CLOSE | ||
951 | case Q_CLOSE: | ||
952 | return; | ||
953 | #endif | ||
944 | } | 954 | } |
945 | } | 955 | } |
946 | } | 956 | } |
@@ -1307,6 +1317,9 @@ int ata_init(void) | |||
1307 | mutex_lock(&ata_mtx); /* Balance unlock below */ | 1317 | mutex_lock(&ata_mtx); /* Balance unlock below */ |
1308 | 1318 | ||
1309 | last_disk_activity = current_tick; | 1319 | last_disk_activity = current_tick; |
1320 | #ifdef ATA_DRIVER_CLOSE | ||
1321 | ata_thread_p = | ||
1322 | #endif | ||
1310 | create_thread(ata_thread, ata_stack, | 1323 | create_thread(ata_thread, ata_stack, |
1311 | sizeof(ata_stack), 0, ata_thread_name | 1324 | sizeof(ata_stack), 0, ata_thread_name |
1312 | IF_PRIO(, PRIORITY_USER_INTERFACE) | 1325 | IF_PRIO(, PRIORITY_USER_INTERFACE) |
@@ -1322,6 +1335,21 @@ int ata_init(void) | |||
1322 | return rc; | 1335 | return rc; |
1323 | } | 1336 | } |
1324 | 1337 | ||
1338 | #ifdef ATA_DRIVER_CLOSE | ||
1339 | void ata_close(void) | ||
1340 | { | ||
1341 | struct thread_entry *thread = ata_thread_p; | ||
1342 | |||
1343 | if (thread == NULL) | ||
1344 | return; | ||
1345 | |||
1346 | ata_thread_p = NULL; | ||
1347 | |||
1348 | queue_post(&ata_queue, Q_CLOSE, 0); | ||
1349 | thread_wait(thread); | ||
1350 | } | ||
1351 | #endif /* ATA_DRIVER_CLOSE */ | ||
1352 | |||
1325 | #if (CONFIG_LED == LED_REAL) | 1353 | #if (CONFIG_LED == LED_REAL) |
1326 | void ata_set_led_enabled(bool enabled) | 1354 | void ata_set_led_enabled(bool enabled) |
1327 | { | 1355 | { |
diff --git a/firmware/drivers/button.c b/firmware/drivers/button.c index 90ff800c88..74c5a97167 100644 --- a/firmware/drivers/button.c +++ b/firmware/drivers/button.c | |||
@@ -410,6 +410,13 @@ void button_init(void) | |||
410 | tick_add_task(button_tick); | 410 | tick_add_task(button_tick); |
411 | } | 411 | } |
412 | 412 | ||
413 | #ifdef BUTTON_DRIVER_CLOSE | ||
414 | void button_close(void) | ||
415 | { | ||
416 | tick_remove_task(button_tick); | ||
417 | } | ||
418 | #endif /* BUTTON_DRIVER_CLOSE */ | ||
419 | |||
413 | #ifdef HAVE_LCD_BITMAP /* only bitmap displays can be flipped */ | 420 | #ifdef HAVE_LCD_BITMAP /* only bitmap displays can be flipped */ |
414 | /* | 421 | /* |
415 | * helper function to swap LEFT/RIGHT, UP/DOWN (if present), and F1/F3 (Recorder) | 422 | * helper function to swap LEFT/RIGHT, UP/DOWN (if present), and F1/F3 (Recorder) |
diff --git a/firmware/export/ata.h b/firmware/export/ata.h index 35538f6354..9b5bd36a5b 100644 --- a/firmware/export/ata.h +++ b/firmware/export/ata.h | |||
@@ -48,6 +48,7 @@ extern bool ata_disk_is_active(void); | |||
48 | extern int ata_hard_reset(void); | 48 | extern int ata_hard_reset(void); |
49 | extern int ata_soft_reset(void); | 49 | extern int ata_soft_reset(void); |
50 | extern int ata_init(void); | 50 | extern int ata_init(void); |
51 | extern void ata_close(void); | ||
51 | extern int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf); | 52 | extern int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf); |
52 | extern int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf); | 53 | extern int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf); |
53 | extern void ata_spin(void); | 54 | extern void ata_spin(void); |
diff --git a/firmware/export/backlight.h b/firmware/export/backlight.h index 35c0f86178..895328d98e 100644 --- a/firmware/export/backlight.h +++ b/firmware/export/backlight.h | |||
@@ -28,6 +28,7 @@ void backlight_set_timeout(int value); | |||
28 | 28 | ||
29 | #ifdef HAVE_BACKLIGHT | 29 | #ifdef HAVE_BACKLIGHT |
30 | void backlight_init(void); | 30 | void backlight_init(void); |
31 | void backlight_close(void); | ||
31 | 32 | ||
32 | int backlight_get_current_timeout(void); | 33 | int backlight_get_current_timeout(void); |
33 | 34 | ||
diff --git a/firmware/export/button.h b/firmware/export/button.h index 6decf6ec69..82ea81ffab 100644 --- a/firmware/export/button.h +++ b/firmware/export/button.h | |||
@@ -29,6 +29,7 @@ | |||
29 | extern struct event_queue button_queue; | 29 | extern struct event_queue button_queue; |
30 | 30 | ||
31 | void button_init (void); | 31 | void button_init (void); |
32 | void button_close(void); | ||
32 | int button_queue_count(void); | 33 | int button_queue_count(void); |
33 | long button_get (bool block); | 34 | long button_get (bool block); |
34 | long button_get_w_tmo(int ticks); | 35 | long button_get_w_tmo(int ticks); |
diff --git a/firmware/export/config-gigabeat-s.h b/firmware/export/config-gigabeat-s.h index d74f05ce9c..a0c05dad45 100644 --- a/firmware/export/config-gigabeat-s.h +++ b/firmware/export/config-gigabeat-s.h | |||
@@ -54,15 +54,6 @@ | |||
54 | /* Define this for LCD backlight available */ | 54 | /* Define this for LCD backlight available */ |
55 | #define HAVE_BACKLIGHT | 55 | #define HAVE_BACKLIGHT |
56 | 56 | ||
57 | #define HAVE_LCD_ENABLE | ||
58 | |||
59 | #define HAVE_BACKLIGHT_BRIGHTNESS | ||
60 | |||
61 | /* Main LCD backlight brightness range and defaults */ | ||
62 | #define MIN_BRIGHTNESS_SETTING 0 | ||
63 | #define MAX_BRIGHTNESS_SETTING 24 | ||
64 | #define DEFAULT_BRIGHTNESS_SETTING 12 | ||
65 | |||
66 | /* Define this if you have a software controlled poweroff */ | 57 | /* Define this if you have a software controlled poweroff */ |
67 | #define HAVE_SW_POWEROFF | 58 | #define HAVE_SW_POWEROFF |
68 | 59 | ||
@@ -78,7 +69,20 @@ | |||
78 | #define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | \ | 69 | #define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | \ |
79 | SAMPR_CAP_11) | 70 | SAMPR_CAP_11) |
80 | 71 | ||
72 | #ifndef BOOTLOADER | ||
73 | /* Not for bootloader */ | ||
74 | #define HAVE_LCD_ENABLE | ||
75 | |||
76 | #define HAVE_BACKLIGHT_BRIGHTNESS | ||
77 | |||
78 | /* Main LCD backlight brightness range and defaults */ | ||
79 | #define MIN_BRIGHTNESS_SETTING 0 | ||
80 | #define MAX_BRIGHTNESS_SETTING 24 | ||
81 | #define DEFAULT_BRIGHTNESS_SETTING 12 | ||
82 | |||
83 | |||
81 | #define HAVE_HEADPHONE_DETECTION | 84 | #define HAVE_HEADPHONE_DETECTION |
85 | #endif /* BOOTLOADER */ | ||
82 | 86 | ||
83 | #ifndef SIMULATOR | 87 | #ifndef SIMULATOR |
84 | 88 | ||
diff --git a/firmware/export/usb.h b/firmware/export/usb.h index 4500cb2cde..ff1f55cd35 100644 --- a/firmware/export/usb.h +++ b/firmware/export/usb.h | |||
@@ -31,7 +31,8 @@ enum { | |||
31 | USB_TRANSFER_COMPLETION, | 31 | USB_TRANSFER_COMPLETION, |
32 | USB_REQUEST_DISK, | 32 | USB_REQUEST_DISK, |
33 | USB_RELEASE_DISK, | 33 | USB_RELEASE_DISK, |
34 | USB_REQUEST_REBOOT | 34 | USB_REQUEST_REBOOT, |
35 | USB_QUIT, | ||
35 | }; | 36 | }; |
36 | 37 | ||
37 | 38 | ||
@@ -89,7 +90,7 @@ struct usb_transfer_completion_event_data | |||
89 | void usb_init(void); | 90 | void usb_init(void); |
90 | void usb_enable(bool on); | 91 | void usb_enable(bool on); |
91 | void usb_start_monitoring(void); | 92 | void usb_start_monitoring(void); |
92 | void usb_stop_monitoring(void); | 93 | void usb_close(void); |
93 | void usb_acknowledge(long id); | 94 | void usb_acknowledge(long id); |
94 | void usb_wait_for_disconnect(struct event_queue *q); | 95 | void usb_wait_for_disconnect(struct event_queue *q); |
95 | int usb_wait_for_disconnect_w_tmo(struct event_queue *q, int ticks); | 96 | int usb_wait_for_disconnect_w_tmo(struct event_queue *q, int ticks); |
diff --git a/firmware/target/arm/imx31/gigabeat-s/ata-target.h b/firmware/target/arm/imx31/gigabeat-s/ata-target.h index 6428e9f41f..8f8083dc8d 100644 --- a/firmware/target/arm/imx31/gigabeat-s/ata-target.h +++ b/firmware/target/arm/imx31/gigabeat-s/ata-target.h | |||
@@ -19,6 +19,10 @@ | |||
19 | #ifndef ATA_TARGET_H | 19 | #ifndef ATA_TARGET_H |
20 | #define ATA_TARGET_H | 20 | #define ATA_TARGET_H |
21 | 21 | ||
22 | #ifdef BOOTLOADER | ||
23 | #define ATA_DRIVER_CLOSE | ||
24 | #endif | ||
25 | |||
22 | /* Plain C read & write loops */ | 26 | /* Plain C read & write loops */ |
23 | #define PREFER_C_READING | 27 | #define PREFER_C_READING |
24 | #define PREFER_C_WRITING | 28 | #define PREFER_C_WRITING |
diff --git a/firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c b/firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c index 4df9be843c..b35e3c1ad0 100644 --- a/firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include "mc13783.h" | 22 | #include "mc13783.h" |
23 | #include "backlight-target.h" | 23 | #include "backlight-target.h" |
24 | 24 | ||
25 | #ifdef HAVE_BACKLIGHT_BRIGHTNESS | ||
25 | /* Table that uses combinations of current level and pwm fraction to get | 26 | /* Table that uses combinations of current level and pwm fraction to get |
26 | * as many uniquely-visible brightness levels as possible. The lowest current | 27 | * as many uniquely-visible brightness levels as possible. The lowest current |
27 | * level for any average current is used even though many combinations give | 28 | * level for any average current is used even though many combinations give |
@@ -60,6 +61,7 @@ static const struct | |||
60 | { 3, 12 }, /* 9 12 7.2 */ | 61 | { 3, 12 }, /* 9 12 7.2 */ |
61 | /* Anything higher is just too much */ | 62 | /* Anything higher is just too much */ |
62 | }; | 63 | }; |
64 | #endif /* HAVE_BACKLIGHT_BRIGHTNESS */ | ||
63 | 65 | ||
64 | bool _backlight_init(void) | 66 | bool _backlight_init(void) |
65 | { | 67 | { |
@@ -85,6 +87,7 @@ void _backlight_off(void) | |||
85 | mc13783_clear(MC13783_LED_CONTROL0, MC13783_LEDEN); | 87 | mc13783_clear(MC13783_LED_CONTROL0, MC13783_LEDEN); |
86 | } | 88 | } |
87 | 89 | ||
90 | #ifdef HAVE_BACKLIGHT_BRIGHTNESS | ||
88 | /* Assumes that the backlight has been initialized */ | 91 | /* Assumes that the backlight has been initialized */ |
89 | void _backlight_set_brightness(int brightness) | 92 | void _backlight_set_brightness(int brightness) |
90 | { | 93 | { |
@@ -106,3 +109,4 @@ void _backlight_set_brightness(int brightness) | |||
106 | 109 | ||
107 | mc13783_write(MC13783_LED_CONTROL2, data); | 110 | mc13783_write(MC13783_LED_CONTROL2, data); |
108 | } | 111 | } |
112 | #endif /* HAVE_BACKLIGHT_BRIGHTNESS */ | ||
diff --git a/firmware/target/arm/imx31/gigabeat-s/backlight-target.h b/firmware/target/arm/imx31/gigabeat-s/backlight-target.h index 7c4b2fa0fd..145df0d930 100644 --- a/firmware/target/arm/imx31/gigabeat-s/backlight-target.h +++ b/firmware/target/arm/imx31/gigabeat-s/backlight-target.h | |||
@@ -19,11 +19,15 @@ | |||
19 | #ifndef BACKLIGHT_TARGET_H | 19 | #ifndef BACKLIGHT_TARGET_H |
20 | #define BACKLIGHT_TARGET_H | 20 | #define BACKLIGHT_TARGET_H |
21 | 21 | ||
22 | #ifdef BOOTLOADER | ||
23 | #define BACKLIGHT_DRIVER_CLOSE | ||
24 | /* Force the whole driver to be built */ | ||
25 | #define BACKLIGHT_FULL_INIT | ||
26 | #endif | ||
27 | |||
22 | bool _backlight_init(void); | 28 | bool _backlight_init(void); |
23 | void _backlight_on(void); | 29 | void _backlight_on(void); |
24 | void _backlight_off(void); | 30 | void _backlight_off(void); |
25 | void _backlight_set_brightness(int brightness); | 31 | void _backlight_set_brightness(int brightness); |
26 | 32 | ||
27 | /* true: backlight fades off - false: backlight fades on */ | ||
28 | void __backlight_dim(bool dim); | ||
29 | #endif | 33 | #endif |
diff --git a/firmware/target/arm/imx31/gigabeat-s/button-imx31.c b/firmware/target/arm/imx31/gigabeat-s/button-imx31.c index e80166bca7..746883d010 100644 --- a/firmware/target/arm/imx31/gigabeat-s/button-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/button-imx31.c | |||
@@ -29,11 +29,16 @@ | |||
29 | 29 | ||
30 | /* Most code in here is taken from the Linux BSP provided by Freescale | 30 | /* Most code in here is taken from the Linux BSP provided by Freescale |
31 | * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved. */ | 31 | * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved. */ |
32 | 32 | #ifdef HAVE_HEADPHONE_DETECTION | |
33 | static bool headphones_detect = false; | 33 | static bool headphones_detect = false; |
34 | #endif | ||
34 | static uint32_t int_btn = BUTTON_NONE; | 35 | static uint32_t int_btn = BUTTON_NONE; |
35 | static bool hold_button = false; | 36 | static bool hold_button = false; |
37 | #ifdef BOOTLOADER | ||
38 | static bool initialized = false; | ||
39 | #else | ||
36 | static bool hold_button_old = false; | 40 | static bool hold_button_old = false; |
41 | #endif | ||
37 | #define _button_hold() (GPIO3_DR & 0x10) | 42 | #define _button_hold() (GPIO3_DR & 0x10) |
38 | 43 | ||
39 | static __attribute__((interrupt("IRQ"))) void KPP_HANDLER(void) | 44 | static __attribute__((interrupt("IRQ"))) void KPP_HANDLER(void) |
@@ -116,6 +121,14 @@ static __attribute__((interrupt("IRQ"))) void KPP_HANDLER(void) | |||
116 | 121 | ||
117 | void button_init_device(void) | 122 | void button_init_device(void) |
118 | { | 123 | { |
124 | #ifdef BOOTLOADER | ||
125 | /* Can be called more than once in the bootloader */ | ||
126 | if (initialized) | ||
127 | return; | ||
128 | |||
129 | initialized = true; | ||
130 | #endif | ||
131 | |||
119 | /* Enable keypad clock */ | 132 | /* Enable keypad clock */ |
120 | imx31_clkctl_module_clock_gating(CG_KPP, CGM_ON_ALL); | 133 | imx31_clkctl_module_clock_gating(CG_KPP, CGM_ON_ALL); |
121 | 134 | ||
@@ -136,15 +149,26 @@ void button_init_device(void) | |||
136 | KPP_KDDR = (KPP_KDDR | (0x7 << 8)) & ~0x1f; | 149 | KPP_KDDR = (KPP_KDDR | (0x7 << 8)) & ~0x1f; |
137 | 150 | ||
138 | /* 5. Clear the KPKD Status Flag and Synchronizer chain. | 151 | /* 5. Clear the KPKD Status Flag and Synchronizer chain. |
139 | * 6. Set the KDIE control bit, and set the KRIE control | 152 | * 6. Set the KDIE control bit bit. */ |
140 | * bit (to force immediate scan). */ | 153 | KPP_KPSR = KPP_KPSR_KDIE | KPP_KPSR_KRSS | KPP_KPSR_KDSC | KPP_KPSR_KPKD; |
141 | KPP_KPSR = KPP_KPSR_KRIE | KPP_KPSR_KDIE | KPP_KPSR_KRSS | | ||
142 | KPP_KPSR_KDSC | KPP_KPSR_KPKR | KPP_KPSR_KPKD; | ||
143 | 154 | ||
144 | /* KPP IRQ at priority 3 */ | 155 | /* KPP IRQ at priority 3 */ |
145 | avic_enable_int(KPP, IRQ, 3, KPP_HANDLER); | 156 | avic_enable_int(KPP, IRQ, 3, KPP_HANDLER); |
146 | } | 157 | } |
147 | 158 | ||
159 | #ifdef BUTTON_DRIVER_CLOSE | ||
160 | void button_close_device(void) | ||
161 | { | ||
162 | int oldlevel = disable_irq_save(); | ||
163 | |||
164 | avic_disable_int(KPP); | ||
165 | KPP_KPSR &= ~(KPP_KPSR_KRIE | KPP_KPSR_KDIE); | ||
166 | int_btn = BUTTON_NONE; | ||
167 | |||
168 | restore_irq(oldlevel); | ||
169 | } | ||
170 | #endif /* BUTTON_DRIVER_CLOSE */ | ||
171 | |||
148 | bool button_hold(void) | 172 | bool button_hold(void) |
149 | { | 173 | { |
150 | return _button_hold(); | 174 | return _button_hold(); |
@@ -155,12 +179,14 @@ int button_read_device(void) | |||
155 | /* Simple poll of GPIO status */ | 179 | /* Simple poll of GPIO status */ |
156 | hold_button = _button_hold(); | 180 | hold_button = _button_hold(); |
157 | 181 | ||
182 | #ifndef BOOTLOADER | ||
158 | /* Backlight hold handling */ | 183 | /* Backlight hold handling */ |
159 | if (hold_button != hold_button_old) | 184 | if (hold_button != hold_button_old) |
160 | { | 185 | { |
161 | hold_button_old = hold_button; | 186 | hold_button_old = hold_button; |
162 | backlight_hold_changed(hold_button); | 187 | backlight_hold_changed(hold_button); |
163 | } | 188 | } |
189 | #endif | ||
164 | 190 | ||
165 | /* Enable the keypad interrupt to cause it to fire if a key is down. | 191 | /* Enable the keypad interrupt to cause it to fire if a key is down. |
166 | * KPP_HANDLER will clear and disable it after the scan. If no key | 192 | * KPP_HANDLER will clear and disable it after the scan. If no key |
@@ -190,6 +216,7 @@ void button_power_set_state(bool pressed) | |||
190 | restore_irq(oldlevel); | 216 | restore_irq(oldlevel); |
191 | } | 217 | } |
192 | 218 | ||
219 | #ifdef HAVE_HEADPHONE_DETECTION | ||
193 | /* This is called from the mc13783 interrupt thread */ | 220 | /* This is called from the mc13783 interrupt thread */ |
194 | void set_headphones_inserted(bool inserted) | 221 | void set_headphones_inserted(bool inserted) |
195 | { | 222 | { |
@@ -203,3 +230,4 @@ bool headphones_inserted(void) | |||
203 | { | 230 | { |
204 | return headphones_detect; | 231 | return headphones_detect; |
205 | } | 232 | } |
233 | #endif /* HAVE_HEADPHONE_DETECTION */ | ||
diff --git a/firmware/target/arm/imx31/gigabeat-s/button-target.h b/firmware/target/arm/imx31/gigabeat-s/button-target.h index e2f68162f7..61d33f8e70 100644 --- a/firmware/target/arm/imx31/gigabeat-s/button-target.h +++ b/firmware/target/arm/imx31/gigabeat-s/button-target.h | |||
@@ -24,8 +24,13 @@ | |||
24 | 24 | ||
25 | #define HAS_BUTTON_HOLD | 25 | #define HAS_BUTTON_HOLD |
26 | 26 | ||
27 | #ifdef BOOTLOADER | ||
28 | #define BUTTON_DRIVER_CLOSE | ||
29 | #endif | ||
30 | |||
27 | bool button_hold(void); | 31 | bool button_hold(void); |
28 | void button_init_device(void); | 32 | void button_init_device(void); |
33 | void button_close_device(void); | ||
29 | int button_read_device(void); | 34 | int button_read_device(void); |
30 | void button_power_set_state(bool pressed); | 35 | void button_power_set_state(bool pressed); |
31 | void set_headphones_inserted(bool inserted); | 36 | void set_headphones_inserted(bool inserted); |
@@ -48,6 +53,8 @@ bool headphones_inserted(void); | |||
48 | #define BUTTON_NEXT (1 << 11) | 53 | #define BUTTON_NEXT (1 << 11) |
49 | #define BUTTON_POWER (1 << 12) /* Read from PMIC */ | 54 | #define BUTTON_POWER (1 << 12) /* Read from PMIC */ |
50 | 55 | ||
56 | #define BUTTON_MAIN (0x1fff) | ||
57 | |||
51 | #define BUTTON_REMOTE 0 | 58 | #define BUTTON_REMOTE 0 |
52 | 59 | ||
53 | #define POWEROFF_BUTTON BUTTON_POWER | 60 | #define POWEROFF_BUTTON BUTTON_POWER |
diff --git a/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c b/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c index 3af4b48b66..ddf8d1360f 100644 --- a/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c | |||
@@ -29,6 +29,10 @@ | |||
29 | #include "adc-target.h" | 29 | #include "adc-target.h" |
30 | #include "usb-target.h" | 30 | #include "usb-target.h" |
31 | 31 | ||
32 | #ifdef BOOTLOADER | ||
33 | #define PMIC_DRIVER_CLOSE | ||
34 | #endif | ||
35 | |||
32 | /* This is all based on communicating with the MC13783 PMU which is on | 36 | /* This is all based on communicating with the MC13783 PMU which is on |
33 | * CSPI2 with the chip select at 0. The LCD controller resides on | 37 | * CSPI2 with the chip select at 0. The LCD controller resides on |
34 | * CSPI3 cs1, but we have no idea how to communicate to it */ | 38 | * CSPI3 cs1, but we have no idea how to communicate to it */ |
@@ -48,10 +52,14 @@ static struct spi_node mc13783_spi = | |||
48 | static int mc13783_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)]; | 52 | static int mc13783_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)]; |
49 | static const char *mc13783_thread_name = "pmic"; | 53 | static const char *mc13783_thread_name = "pmic"; |
50 | static struct wakeup mc13783_wake; | 54 | static struct wakeup mc13783_wake; |
55 | #ifdef PMIC_DRIVER_CLOSE | ||
56 | static bool pmic_close = false; | ||
57 | static struct thread_entry *mc13783_thread_p = NULL; | ||
58 | #endif | ||
51 | 59 | ||
52 | /* The next two functions are rather target-specific but they'll just be left | 60 | /* The next two functions are rather target-specific but they'll just be left |
53 | * here for the moment */ | 61 | * here for the moment */ |
54 | static __attribute__((noreturn)) void mc13783_interrupt_thread(void) | 62 | static void mc13783_interrupt_thread(void) |
55 | { | 63 | { |
56 | const unsigned char status_regs[2] = | 64 | const unsigned char status_regs[2] = |
57 | { | 65 | { |
@@ -76,7 +84,9 @@ static __attribute__((noreturn)) void mc13783_interrupt_thread(void) | |||
76 | 84 | ||
77 | value = mc13783_read(MC13783_INTERRUPT_SENSE1); | 85 | value = mc13783_read(MC13783_INTERRUPT_SENSE1); |
78 | button_power_set_state((value & MC13783_ONOFD1) == 0); | 86 | button_power_set_state((value & MC13783_ONOFD1) == 0); |
87 | #ifdef HAVE_HEADPHONE_DETECTION | ||
79 | set_headphones_inserted((value & MC13783_ONOFD2) == 0); | 88 | set_headphones_inserted((value & MC13783_ONOFD2) == 0); |
89 | #endif | ||
80 | 90 | ||
81 | pending[0] = pending[1] = 0xffffff; | 91 | pending[0] = pending[1] = 0xffffff; |
82 | mc13783_write_regset(status_regs, pending, 2); | 92 | mc13783_write_regset(status_regs, pending, 2); |
@@ -90,6 +100,14 @@ static __attribute__((noreturn)) void mc13783_interrupt_thread(void) | |||
90 | { | 100 | { |
91 | wakeup_wait(&mc13783_wake, TIMEOUT_BLOCK); | 101 | wakeup_wait(&mc13783_wake, TIMEOUT_BLOCK); |
92 | 102 | ||
103 | #ifdef PMIC_DRIVER_CLOSE | ||
104 | if (pmic_close) | ||
105 | { | ||
106 | gpio_disable_event(MC13783_GPIO_NUM, MC13783_EVENT_ID); | ||
107 | return; | ||
108 | } | ||
109 | #endif | ||
110 | |||
93 | mc13783_read_regset(status_regs, pending, 2); | 111 | mc13783_read_regset(status_regs, pending, 2); |
94 | mc13783_write_regset(status_regs, pending, 2); | 112 | mc13783_write_regset(status_regs, pending, 2); |
95 | 113 | ||
@@ -130,9 +148,10 @@ static __attribute__((noreturn)) void mc13783_interrupt_thread(void) | |||
130 | 148 | ||
131 | if (pending[1] & MC13783_ONOFD1) | 149 | if (pending[1] & MC13783_ONOFD1) |
132 | button_power_set_state((value & MC13783_ONOFD1) == 0); | 150 | button_power_set_state((value & MC13783_ONOFD1) == 0); |
133 | 151 | #ifdef HAVE_HEADPHONE_DETECTION | |
134 | if (pending[1] & MC13783_ONOFD2) | 152 | if (pending[1] & MC13783_ONOFD2) |
135 | set_headphones_inserted((value & MC13783_ONOFD2) == 0); | 153 | set_headphones_inserted((value & MC13783_ONOFD2) == 0); |
154 | #endif | ||
136 | } | 155 | } |
137 | } | 156 | } |
138 | } | 157 | } |
@@ -161,10 +180,29 @@ void mc13783_init(void) | |||
161 | 180 | ||
162 | MC13783_GPIO_ISR = (1ul << MC13783_GPIO_LINE); | 181 | MC13783_GPIO_ISR = (1ul << MC13783_GPIO_LINE); |
163 | 182 | ||
164 | create_thread(mc13783_interrupt_thread, mc13783_thread_stack, | 183 | #ifdef PMIC_DRIVER_CLOSE |
165 | sizeof(mc13783_thread_stack), 0, mc13783_thread_name | 184 | mc13783_thread_p = |
166 | IF_PRIO(, PRIORITY_REALTIME) IF_COP(, CPU)); | 185 | #endif |
186 | create_thread(mc13783_interrupt_thread, | ||
187 | mc13783_thread_stack, sizeof(mc13783_thread_stack), 0, | ||
188 | mc13783_thread_name IF_PRIO(, PRIORITY_REALTIME) IF_COP(, CPU)); | ||
189 | } | ||
190 | |||
191 | #ifdef PMIC_DRIVER_CLOSE | ||
192 | void mc13783_close(void) | ||
193 | { | ||
194 | struct thread_entry *thread = mc13783_thread_p; | ||
195 | |||
196 | if (thread == NULL) | ||
197 | return; | ||
198 | |||
199 | mc13783_thread_p = NULL; | ||
200 | |||
201 | pmic_close = true; | ||
202 | wakeup_signal(&mc13783_wake); | ||
203 | thread_wait(thread); | ||
167 | } | 204 | } |
205 | #endif | ||
168 | 206 | ||
169 | uint32_t mc13783_set(unsigned address, uint32_t bits) | 207 | uint32_t mc13783_set(unsigned address, uint32_t bits) |
170 | { | 208 | { |
diff --git a/firmware/target/arm/imx31/gigabeat-s/system-imx31.c b/firmware/target/arm/imx31/gigabeat-s/system-imx31.c index 3ec46bae67..1c3abc64fc 100644 --- a/firmware/target/arm/imx31/gigabeat-s/system-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/system-imx31.c | |||
@@ -117,6 +117,7 @@ void system_prepare_fw_start(void) | |||
117 | { | 117 | { |
118 | disable_interrupt(IRQ_FIQ_STATUS); | 118 | disable_interrupt(IRQ_FIQ_STATUS); |
119 | avic_disable_int(ALL); | 119 | avic_disable_int(ALL); |
120 | mc13783_close(); | ||
120 | tick_stop(); | 121 | tick_stop(); |
121 | } | 122 | } |
122 | #endif | 123 | #endif |
diff --git a/firmware/target/arm/imx31/gigabeat-s/usb-target.h b/firmware/target/arm/imx31/gigabeat-s/usb-target.h index 8c9dcfc65f..7ecd9a7d49 100644 --- a/firmware/target/arm/imx31/gigabeat-s/usb-target.h +++ b/firmware/target/arm/imx31/gigabeat-s/usb-target.h | |||
@@ -19,6 +19,10 @@ | |||
19 | #ifndef USB_TARGET_H | 19 | #ifndef USB_TARGET_H |
20 | #define USB_TARGET_H | 20 | #define USB_TARGET_H |
21 | 21 | ||
22 | #ifdef BOOTLOADER | ||
23 | #define USB_DRIVER_CLOSE | ||
24 | #endif | ||
25 | |||
22 | void usb_set_status(bool plugged); | 26 | void usb_set_status(bool plugged); |
23 | bool usb_init_device(void); | 27 | bool usb_init_device(void); |
24 | int usb_detect(void); | 28 | int usb_detect(void); |
diff --git a/firmware/usb.c b/firmware/usb.c index 3867bfb496..90991e25fd 100644 --- a/firmware/usb.c +++ b/firmware/usb.c | |||
@@ -172,6 +172,10 @@ static void usb_thread(void) | |||
172 | queue_wait(&usb_queue, &ev); | 172 | queue_wait(&usb_queue, &ev); |
173 | switch(ev.id) | 173 | switch(ev.id) |
174 | { | 174 | { |
175 | #ifdef USB_DRIVER_CLOSE | ||
176 | case USB_QUIT: | ||
177 | return; | ||
178 | #endif | ||
175 | #ifdef HAVE_USBSTACK | 179 | #ifdef HAVE_USBSTACK |
176 | case USB_TRANSFER_COMPLETION: | 180 | case USB_TRANSFER_COMPLETION: |
177 | usb_core_handle_transfer_completion((struct usb_transfer_completion_event_data*)ev.data); | 181 | usb_core_handle_transfer_completion((struct usb_transfer_completion_event_data*)ev.data); |
@@ -531,13 +535,22 @@ void usb_start_monitoring(void) | |||
531 | usb_monitor_enabled = true; | 535 | usb_monitor_enabled = true; |
532 | } | 536 | } |
533 | 537 | ||
534 | #ifdef TOSHIBA_GIGABEAT_S | 538 | #ifdef USB_DRIVER_CLOSE |
535 | void usb_stop_monitoring(void) | 539 | void usb_close(void) |
536 | { | 540 | { |
541 | struct thread_entry *thread = usb_thread_entry; | ||
542 | usb_thread_entry = NULL; | ||
543 | |||
544 | if (thread == NULL) | ||
545 | return; | ||
546 | |||
537 | tick_remove_task(usb_tick); | 547 | tick_remove_task(usb_tick); |
538 | usb_monitor_enabled = false; | 548 | usb_monitor_enabled = false; |
549 | |||
550 | queue_post(&usb_queue, USB_QUIT, 0); | ||
551 | thread_wait(thread); | ||
539 | } | 552 | } |
540 | #endif | 553 | #endif /* USB_DRIVER_CLOSE */ |
541 | 554 | ||
542 | bool usb_inserted(void) | 555 | bool usb_inserted(void) |
543 | { | 556 | { |