summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/backlight.c49
-rw-r--r--firmware/drivers/ata.c28
-rw-r--r--firmware/drivers/button.c7
-rw-r--r--firmware/export/ata.h1
-rw-r--r--firmware/export/backlight.h1
-rw-r--r--firmware/export/button.h1
-rw-r--r--firmware/export/config-gigabeat-s.h22
-rw-r--r--firmware/export/usb.h5
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/ata-target.h4
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c4
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/backlight-target.h8
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/button-imx31.c38
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/button-target.h7
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c48
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/system-imx31.c1
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/usb-target.h4
-rw-r--r--firmware/usb.c19
17 files changed, 214 insertions, 33 deletions
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
90enum { 95enum {
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
109static void backlight_thread(void); 117static void backlight_thread(void);
110static long backlight_stack[DEFAULT_STACK_SIZE/sizeof(long)]; 118static long backlight_stack[DEFAULT_STACK_SIZE/sizeof(long)];
111static const char backlight_thread_name[] = "backlight"; 119static const char backlight_thread_name[] = "backlight";
112static struct event_queue backlight_queue; 120static struct event_queue backlight_queue;
121#ifdef BACKLIGHT_DRIVER_CLOSE
122static struct thread_entry *backlight_thread_p = NULL;
123#endif
113 124
114static int backlight_timer SHAREDBSS_ATTR; 125static int backlight_timer SHAREDBSS_ATTR;
115static int backlight_timeout SHAREDBSS_ATTR; 126static 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
164static int remote_backlight_timer; 175static 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
171static int remote_backlight_on_button_hold = 0; 182static 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
176const signed char lcd_sleep_timeout_value[10] = 187const 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
644void 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
624void backlight_on(void) 659void 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)
795void backlight_init(void) 830void 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
827void buttonlight_set_brightness(int val) { (void)val; } 862void 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
71static 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? */
71struct ata_lock 76struct 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
1339void 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)
1326void ata_set_led_enabled(bool enabled) 1354void 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
414void 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);
48extern int ata_hard_reset(void); 48extern int ata_hard_reset(void);
49extern int ata_soft_reset(void); 49extern int ata_soft_reset(void);
50extern int ata_init(void); 50extern int ata_init(void);
51extern void ata_close(void);
51extern int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf); 52extern int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf);
52extern int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf); 53extern int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf);
53extern void ata_spin(void); 54extern 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
30void backlight_init(void); 30void backlight_init(void);
31void backlight_close(void);
31 32
32int backlight_get_current_timeout(void); 33int 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 @@
29extern struct event_queue button_queue; 29extern struct event_queue button_queue;
30 30
31void button_init (void); 31void button_init (void);
32void button_close(void);
32int button_queue_count(void); 33int button_queue_count(void);
33long button_get (bool block); 34long button_get (bool block);
34long button_get_w_tmo(int ticks); 35long 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
89void usb_init(void); 90void usb_init(void);
90void usb_enable(bool on); 91void usb_enable(bool on);
91void usb_start_monitoring(void); 92void usb_start_monitoring(void);
92void usb_stop_monitoring(void); 93void usb_close(void);
93void usb_acknowledge(long id); 94void usb_acknowledge(long id);
94void usb_wait_for_disconnect(struct event_queue *q); 95void usb_wait_for_disconnect(struct event_queue *q);
95int usb_wait_for_disconnect_w_tmo(struct event_queue *q, int ticks); 96int 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
64bool _backlight_init(void) 66bool _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 */
89void _backlight_set_brightness(int brightness) 92void _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
22bool _backlight_init(void); 28bool _backlight_init(void);
23void _backlight_on(void); 29void _backlight_on(void);
24void _backlight_off(void); 30void _backlight_off(void);
25void _backlight_set_brightness(int brightness); 31void _backlight_set_brightness(int brightness);
26 32
27/* true: backlight fades off - false: backlight fades on */
28void __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
33static bool headphones_detect = false; 33static bool headphones_detect = false;
34#endif
34static uint32_t int_btn = BUTTON_NONE; 35static uint32_t int_btn = BUTTON_NONE;
35static bool hold_button = false; 36static bool hold_button = false;
37#ifdef BOOTLOADER
38static bool initialized = false;
39#else
36static bool hold_button_old = false; 40static bool hold_button_old = false;
41#endif
37#define _button_hold() (GPIO3_DR & 0x10) 42#define _button_hold() (GPIO3_DR & 0x10)
38 43
39static __attribute__((interrupt("IRQ"))) void KPP_HANDLER(void) 44static __attribute__((interrupt("IRQ"))) void KPP_HANDLER(void)
@@ -116,6 +121,14 @@ static __attribute__((interrupt("IRQ"))) void KPP_HANDLER(void)
116 121
117void button_init_device(void) 122void 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
160void 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
148bool button_hold(void) 172bool 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 */
194void set_headphones_inserted(bool inserted) 221void 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
27bool button_hold(void); 31bool button_hold(void);
28void button_init_device(void); 32void button_init_device(void);
33void button_close_device(void);
29int button_read_device(void); 34int button_read_device(void);
30void button_power_set_state(bool pressed); 35void button_power_set_state(bool pressed);
31void set_headphones_inserted(bool inserted); 36void 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 =
48static int mc13783_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)]; 52static int mc13783_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)];
49static const char *mc13783_thread_name = "pmic"; 53static const char *mc13783_thread_name = "pmic";
50static struct wakeup mc13783_wake; 54static struct wakeup mc13783_wake;
55#ifdef PMIC_DRIVER_CLOSE
56static bool pmic_close = false;
57static 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 */
54static __attribute__((noreturn)) void mc13783_interrupt_thread(void) 62static 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
192void 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
169uint32_t mc13783_set(unsigned address, uint32_t bits) 207uint32_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
22void usb_set_status(bool plugged); 26void usb_set_status(bool plugged);
23bool usb_init_device(void); 27bool usb_init_device(void);
24int usb_detect(void); 28int 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
535void usb_stop_monitoring(void) 539void 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
542bool usb_inserted(void) 555bool usb_inserted(void)
543{ 556{