diff options
Diffstat (limited to 'firmware/backlight.c')
| -rw-r--r-- | firmware/backlight.c | 306 |
1 files changed, 233 insertions, 73 deletions
diff --git a/firmware/backlight.c b/firmware/backlight.c index cd1fbaf..f35e87a 100644 --- a/firmware/backlight.c +++ b/firmware/backlight.c @@ -27,15 +27,16 @@ #include "usb.h" #include "power.h" #include "system.h" +#include "button.h" #include "timer.h" #include "backlight.h" #ifdef HAVE_BACKLIGHT_BRIGHTNESS -#include "pcf50606.h" /* iRiver brightness */ +#include "pcf50606.h" /* iRiver, iAudio X5 brightness */ #endif - -#if (CONFIG_BACKLIGHT == BL_IRIVER_H300) -#include "lcd.h" /* for lcd_enable() */ + +#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) +#include "lcd.h" /* for lcd_enable() and lcd_sleep() */ #endif #ifdef HAVE_REMOTE_LCD #include "lcd-remote.h" @@ -61,11 +62,11 @@ static inline void __backlight_off(void) static inline void __backlight_on(void) { #if CONFIG_BACKLIGHT == BL_IRIVER_H100 - and_l(~0x00020000, &GPIO1_OUT); + and_l(~0x00020000, &GPIO1_OUT); #elif CONFIG_BACKLIGHT == BL_IRIVER_H300 lcd_enable(true); sleep(HZ/100); /* lcd needs time - avoid flashing for dark screens */ - or_l(0x00020000, &GPIO1_OUT); + or_l(0x00020000, &GPIO1_OUT); #elif CONFIG_BACKLIGHT == BL_RTC /* Enable square wave */ rtc_write(0x0a, rtc_read(0x0a) | 0x40); @@ -148,9 +149,17 @@ const signed char backlight_timeout_value[19] = #define REMOTE_BACKLIGHT_ON 3 #define REMOTE_BACKLIGHT_OFF 4 #define BACKLIGHT_UNBOOST_CPU 5 +#ifdef HAVE_LCD_SLEEP +#define LCD_SLEEP 6 +#endif static void backlight_thread(void); static long backlight_stack[DEFAULT_STACK_SIZE/sizeof(long)]; +#ifdef X5_BACKLIGHT_SHUTDOWN +#define BACKLIGHT_QUIT 256 +/* Need to save this for x5 shutdown */ +static int backlight_thread_id; +#endif static const char backlight_thread_name[] = "backlight"; static struct event_queue backlight_queue; @@ -159,6 +168,9 @@ static int backlight_timeout = 5*HZ; #ifdef CONFIG_CHARGING static int backlight_timeout_plugged = 5*HZ; #endif +#ifdef HAS_BUTTON_HOLD +static int backlight_on_button_hold = 0; +#endif #ifdef HAVE_REMOTE_LCD static int remote_backlight_timer; @@ -168,6 +180,15 @@ static int remote_backlight_timeout_plugged = 5*HZ; #endif #endif +#ifdef HAVE_LCD_SLEEP +const signed char lcd_sleep_timeout_value[10] = +{ + -1, 0, 5, 10, 15, 20, 30, 45, 60, 90 +}; +static int lcd_sleep_timer; +static int lcd_sleep_timeout = 10*HZ; +#endif + #if defined(HAVE_BACKLIGHT_PWM_FADING) && !defined(SIMULATOR) /* backlight fading */ #define BL_PWM_INTERVAL 5000 /* Cycle interval in µs */ @@ -318,6 +339,9 @@ static void _backlight_on(void) #else __backlight_on(); #endif +#ifdef HAVE_LCD_SLEEP + lcd_sleep_timer = 0; /* LCD should be awake already */ +#endif } static void _backlight_off(void) @@ -333,6 +357,17 @@ static void _backlight_off(void) #else __backlight_off(); #endif + +#ifdef HAVE_LCD_SLEEP + /* Start LCD sleep countdown */ + if (lcd_sleep_timeout < 0) + { + lcd_sleep_timer = 0; /* Setting == Always */ + lcd_sleep(); + } + else + lcd_sleep_timer = lcd_sleep_timeout; +#endif } #ifdef HAVE_REMOTE_LCD @@ -366,13 +401,79 @@ static void __remote_backlight_off(void) #endif } #endif /* TARGET_TREE */ -#endif /* HAVE_REMOTE_LCD */ #endif /* SIMULATOR */ +#endif /* HAVE_REMOTE_LCD */ + +/* Update state of backlight according to timeout setting */ +static void backlight_update_state(void) +{ +#ifdef CONFIG_CHARGING + if (charger_inserted() +#ifdef HAVE_USB_POWER + || usb_powered() +#endif + ) + backlight_timer = backlight_timeout_plugged; + else +#endif + backlight_timer = backlight_timeout; + + /* Backlight == OFF in the setting? */ + if (backlight_timer < 0) + { + backlight_timer = 0; /* Disable the timeout */ +#ifdef HAS_BUTTON_HOLD + if (backlight_on_button_hold == 2 && button_hold()) + return; /* Keep on if "On" */ +#endif + _backlight_off(); + } + else + { +#ifdef HAS_BUTTON_HOLD + if (backlight_on_button_hold == 1 && button_hold()) + { + /* Keep off if "Off". */ + backlight_timer = 0; /* Disable the timeout */ + return; + } +#endif + _backlight_on(); + } +} + +#ifdef HAVE_REMOTE_LCD +/* Update state of remote backlight according to timeout setting */ +static void remote_backlight_update_state(void) +{ +#ifdef CONFIG_CHARGING + if (charger_inserted() +#ifdef HAVE_USB_POWER + || usb_powered() +#endif + ) + remote_backlight_timer = remote_backlight_timeout_plugged; + else +#endif + remote_backlight_timer = remote_backlight_timeout; + + /* Backlight == OFF in the setting? */ + if (remote_backlight_timer < 0) + { + remote_backlight_timer = 0; /* Disable the timeout */ + __remote_backlight_off(); + } + else + { + __remote_backlight_on(); + } +} +#endif /* HAVE_REMOTE_LCD */ void backlight_thread(void) { struct event ev; - + while(1) { queue_wait(&backlight_queue, &ev); @@ -380,61 +481,39 @@ void backlight_thread(void) { #ifdef HAVE_REMOTE_LCD case REMOTE_BACKLIGHT_ON: -#ifdef CONFIG_CHARGING - if (charger_inserted() -#ifdef HAVE_USB_POWER - || usb_powered() -#endif - ) - remote_backlight_timer = remote_backlight_timeout_plugged; - else -#endif - remote_backlight_timer = remote_backlight_timeout; - - /* Backlight == OFF in the setting? */ - if (remote_backlight_timer < 0) - { - remote_backlight_timer = 0; /* Disable the timeout */ - __remote_backlight_off(); - } - else - { - __remote_backlight_on(); - } + remote_backlight_update_state(); break; case REMOTE_BACKLIGHT_OFF: + remote_backlight_timer = 0; /* Disable the timeout */ __remote_backlight_off(); break; - -#endif /* HAVE_REMOTE_LCD */ +#endif case BACKLIGHT_ON: -#ifdef CONFIG_CHARGING - if (charger_inserted() -#ifdef HAVE_USB_POWER - || usb_powered() -#endif - ) - backlight_timer = backlight_timeout_plugged; - else -#endif - backlight_timer = backlight_timeout; - - if (backlight_timer < 0) /* Backlight == OFF in the setting? */ - { - backlight_timer = 0; /* Disable the timeout */ - _backlight_off(); - } - else - { - _backlight_on(); - } + backlight_update_state(); break; - + case BACKLIGHT_OFF: + backlight_timer = 0; /* Disable the timeout */ +#ifdef HAS_BUTTON_HOLD + if (backlight_on_button_hold == 2 && button_hold()) + break; /* Keep on if "On" */ +#endif _backlight_off(); break; +#ifdef HAVE_LCD_SLEEP + case LCD_SLEEP: + lcd_sleep(); + break; +#endif + +#ifdef X5_BACKLIGHT_SHUTDOWN + case BACKLIGHT_QUIT: + remove_thread(backlight_thread_id); + break; +#endif + #if defined(HAVE_BACKLIGHT_PWM_FADING) && defined(CPU_COLDFIRE) \ && !defined(SIMULATOR) case BACKLIGHT_UNBOOST_CPU: @@ -451,8 +530,8 @@ void backlight_thread(void) case SYS_USB_DISCONNECTED: usb_acknowledge(SYS_USB_DISCONNECTED_ACK); break; - } - } + } /* end switch */ + } /* end while */ } static void backlight_tick(void) @@ -483,6 +562,18 @@ static void backlight_tick(void) backlight_off(); } } +#ifdef HAVE_LCD_SLEEP + else if(lcd_sleep_timer) + { + lcd_sleep_timer--; + if(lcd_sleep_timer == 0) + { + /* Queue on bl thread or freeze! */ + queue_post(&backlight_queue, LCD_SLEEP, NULL); + } + } +#endif /* HAVE_LCD_SLEEP */ + #ifdef HAVE_REMOTE_LCD if(remote_backlight_timer) { @@ -492,12 +583,15 @@ static void backlight_tick(void) remote_backlight_off(); } } -#endif +#endif /* HAVE_REMOVE_LCD */ } void backlight_init(void) { queue_init(&backlight_queue); +#ifdef X5_BACKLIGHT_SHUTDOWN + backlight_thread_id = +#endif create_thread(backlight_thread, backlight_stack, sizeof(backlight_stack), backlight_thread_name); tick_add_task(backlight_tick); @@ -516,13 +610,26 @@ void backlight_init(void) or_b(0x40, &PAIORH); /* ..and output */ #elif CONFIG_BACKLIGHT == BL_GMINI P1CON |= 0x10; /* P1.4 C-MOS output mode */ -#endif +#endif backlight_on(); #ifdef HAVE_REMOTE_LCD remote_backlight_on(); #endif } +#ifdef X5_BACKLIGHT_SHUTDOWN +void x5_backlight_shutdown(void) +{ + /* Turn on the screen and don't let anyone else mess with it. Called + from clean_shutdown in misc.c. */ + queue_empty(&backlight_queue); + tick_remove_task(backlight_tick); + /* Next time the thread runs, if at all, it will just remove itself. */ + queue_post(&backlight_queue, BACKLIGHT_QUIT, NULL); + __backlight_on(); +} +#endif /* X5_BACKLIGHT_SHUTDOWN */ + void backlight_on(void) { queue_post(&backlight_queue, BACKLIGHT_ON, NULL); @@ -562,22 +669,72 @@ int backlight_get_current_timeout(void) void backlight_set_timeout(int index) { if((unsigned)index >= sizeof(backlight_timeout_value)) - /* if given a weird value, use 0 */ - index=0; + /* if given a weird value, use default */ + index = 6; backlight_timeout = HZ * backlight_timeout_value[index]; - backlight_on(); + backlight_update_state(); } #ifdef CONFIG_CHARGING void backlight_set_timeout_plugged(int index) { if((unsigned)index >= sizeof(backlight_timeout_value)) - /* if given a weird value, use 0 */ - index=0; + /* if given a weird value, use default */ + index = 6; backlight_timeout_plugged = HZ * backlight_timeout_value[index]; - backlight_on(); + backlight_update_state(); } -#endif +#endif /* CONFIG_CHARGING */ + +#ifdef HAS_BUTTON_HOLD +/* Hold button change event handler. */ +void backlight_hold_changed(bool hold_button) +{ + /* Hold switch overrides all backlight behavior except when + set to "Normal" */ + /* Queue or freeze */ + if (hold_button && backlight_on_button_hold == 1) + { + backlight_off(); /* setting == Off */ + } + else /* setting == On, Normal, no hold button, or anything else */ + backlight_on(); +} + +void backlight_set_on_button_hold(int index) +{ + if ((unsigned)index >= 3) + /* if given a weird value, use default */ + index = 0; + + if (index == backlight_on_button_hold) + return; + + backlight_on_button_hold = index; + backlight_hold_changed(button_hold()); +} +#endif /* HAS_BUTTON_HOLD */ + +#ifdef HAVE_LCD_SLEEP +void lcd_set_sleep_after_backlight_off(int index) +{ + if ((unsigned)index >= sizeof(lcd_sleep_timeout_value)) + /* if given a weird value, use default */ + index = 3; + + lcd_sleep_timeout = HZ * lcd_sleep_timeout_value[index]; + + if (backlight_timer > 0 || backlight_get_current_timeout() == 0) + /* Timer will be set when bl turns off or bl set to on. */ + return; + + /* Backlight is Off */ + if (lcd_sleep_timeout < 0) + lcd_sleep_timer = 1; /* Always - sleep next tick */ + else + lcd_sleep_timer = lcd_sleep_timeout; /* Never, other */ +} +#endif /* HAVE_LCD_SLEEP */ #ifdef HAVE_REMOTE_LCD void remote_backlight_on(void) @@ -593,22 +750,22 @@ void remote_backlight_off(void) void remote_backlight_set_timeout(int index) { if((unsigned)index >= sizeof(backlight_timeout_value)) - /* if given a weird value, use 0 */ - index=0; + /* if given a weird value, use default */ + index=6; remote_backlight_timeout = HZ * backlight_timeout_value[index]; - remote_backlight_on(); + remote_backlight_update_state(); } #ifdef CONFIG_CHARGING void remote_backlight_set_timeout_plugged(int index) { if((unsigned)index >= sizeof(backlight_timeout_value)) - /* if given a weird value, use 0 */ - index=0; + /* if given a weird value, use default */ + index=6; remote_backlight_timeout_plugged = HZ * backlight_timeout_value[index]; - remote_backlight_on(); + remote_backlight_update_state(); } -#endif +#endif /* CONFIG_CHARGING */ /* return value in ticks; 0 means always on, <0 means always off */ int remote_backlight_get_current_timeout(void) @@ -639,7 +796,8 @@ bool is_remote_backlight_on(void) #endif /* HAVE_REMOTE_LCD */ -#else /* no backlight, empty dummy functions */ +#else /* !defined(CONFIG_BACKLIGHT) || defined(BOOTLOADER) + -- no backlight, empty dummy functions */ #if defined(BOOTLOADER) && defined(CONFIG_BACKLIGHT) void backlight_init(void) @@ -662,8 +820,10 @@ void remote_backlight_off(void) {} void remote_backlight_set_timeout(int index) {(void)index;} bool is_remote_backlight_on(void) {return true;} #endif -#endif /* #ifdef CONFIG_BACKLIGHT */ +#endif /* defined(CONFIG_BACKLIGHT) && !defined(BOOTLOADER) */ +/* TODO: Move low level code to target/ tree. Create + __backlight_set_brightness and call from here. */ #ifdef HAVE_BACKLIGHT_BRIGHTNESS #if defined(IRIVER_H300_SERIES) || defined(IAUDIO_X5) void backlight_set_brightness(int val) @@ -692,5 +852,5 @@ void backlight_set_brightness(int val) #endif } #endif -#endif +#endif /* HAVE_BACKLIGHT_BRIGHTNESS */ |