fuzev2: prevent button light flickering when accessing µSD
[kugel-rb.git] / firmware / backlight.c
blob27bc8a453f312ecce2e090d85eb471500a52206f
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
11 * Additional work by Martin Ritter (2007) and Thomas Martitz (2008)
12 * for backlight thread fading
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
23 #include "config.h"
24 #include <stdlib.h>
25 #include "cpu.h"
26 #include "kernel.h"
27 #include "thread.h"
28 #include "i2c.h"
29 #include "debug.h"
30 #include "rtc.h"
31 #include "usb.h"
32 #include "power.h"
33 #include "system.h"
34 #include "button.h"
35 #include "timer.h"
36 #include "backlight.h"
37 #include "lcd.h"
38 #include "screendump.h"
40 #ifdef HAVE_REMOTE_LCD
41 #include "lcd-remote.h"
42 #endif
43 #ifndef SIMULATOR
44 #include "backlight-target.h"
45 #else
46 #include "backlight-sim.h"
47 #endif
49 #if (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_SETTING) \
50 || (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_HW_REG)
51 #include "backlight-sw-fading.h"
52 #endif
54 #if defined(HAVE_BACKLIGHT) && defined(BACKLIGHT_FULL_INIT)
56 #define BACKLIGHT_FADE_IN_THREAD \
57 (CONFIG_BACKLIGHT_FADING & (BACKLIGHT_FADING_SW_SETTING \
58 |BACKLIGHT_FADING_SW_HW_REG \
59 |BACKLIGHT_FADING_PWM) )
61 #define BACKLIGHT_THREAD_TIMEOUT HZ
63 enum {
64 BACKLIGHT_ON,
65 BACKLIGHT_OFF,
66 BACKLIGHT_TMO_CHANGED,
67 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
68 BACKLIGHT_BRIGHTNESS_CHANGED,
69 #endif
70 #ifdef HAVE_REMOTE_LCD
71 REMOTE_BACKLIGHT_ON,
72 REMOTE_BACKLIGHT_OFF,
73 REMOTE_BACKLIGHT_TMO_CHANGED,
74 #endif
75 #if defined(_BACKLIGHT_FADE_BOOST) || defined(_BACKLIGHT_FADE_ENABLE)
76 BACKLIGHT_FADE_FINISH,
77 #endif
78 #ifdef HAVE_LCD_SLEEP
79 LCD_SLEEP,
80 #endif
81 #ifdef HAVE_BUTTON_LIGHT
82 BUTTON_LIGHT_ON,
83 BUTTON_LIGHT_OFF,
84 BUTTON_LIGHT_TMO_CHANGED,
85 #ifdef HAVE_BUTTONLIGHT_BRIGHTNESS
86 BUTTON_LIGHT_BRIGHTNESS_CHANGED,
87 #endif
88 #endif /* HAVE_BUTTON_LIGHT */
89 #ifdef BACKLIGHT_DRIVER_CLOSE
90 BACKLIGHT_QUIT,
91 #endif
94 static void backlight_thread(void);
95 static long backlight_stack[DEFAULT_STACK_SIZE/sizeof(long)];
96 static const char backlight_thread_name[] = "backlight";
97 static struct event_queue backlight_queue;
98 #ifdef BACKLIGHT_DRIVER_CLOSE
99 static unsigned int backlight_thread_id = 0;
100 #endif
102 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
103 int backlight_brightness = DEFAULT_BRIGHTNESS_SETTING;
104 #endif
105 static int backlight_timer SHAREDBSS_ATTR;
106 static int backlight_timeout_normal = 5*HZ;
107 #if CONFIG_CHARGING
108 static int backlight_timeout_plugged = 5*HZ;
109 #endif
110 #ifdef HAS_BUTTON_HOLD
111 static int backlight_on_button_hold = 0;
112 #endif
113 static void backlight_timeout_handler(void);
115 #ifdef HAVE_BUTTON_LIGHT
116 static int buttonlight_timer;
117 static int buttonlight_timeout = 5*HZ;
119 /* Update state of buttonlight according to timeout setting */
120 static void buttonlight_update_state(void)
122 buttonlight_timer = buttonlight_timeout;
124 /* Buttonlight == OFF in the setting? */
125 if (buttonlight_timer < 0)
127 buttonlight_timer = 0; /* Disable the timeout */
128 _buttonlight_off();
130 else
131 _buttonlight_on();
134 /* external interface */
135 void buttonlight_on(void)
137 queue_remove_from_head(&backlight_queue, BUTTON_LIGHT_ON);
138 queue_post(&backlight_queue, BUTTON_LIGHT_ON, 0);
141 void buttonlight_off(void)
143 queue_post(&backlight_queue, BUTTON_LIGHT_OFF, 0);
146 void buttonlight_set_timeout(int value)
148 buttonlight_timeout = HZ * value;
149 queue_post(&backlight_queue, BUTTON_LIGHT_TMO_CHANGED, 0);
152 int buttonlight_get_current_timeout(void)
154 return buttonlight_timeout;
157 #endif /* HAVE_BUTTON_LIGHT */
159 #ifdef HAVE_REMOTE_LCD
160 static int remote_backlight_timer;
161 static int remote_backlight_timeout_normal = 5*HZ;
162 #if CONFIG_CHARGING
163 static int remote_backlight_timeout_plugged = 5*HZ;
164 #endif
165 #ifdef HAS_REMOTE_BUTTON_HOLD
166 static int remote_backlight_on_button_hold = 0;
167 #endif
168 #endif /* HAVE_REMOTE_LCD */
170 #ifdef HAVE_LCD_SLEEP
171 #ifdef HAVE_LCD_SLEEP_SETTING
172 const signed char lcd_sleep_timeout_value[10] =
174 -1, 0, 5, 10, 15, 20, 30, 45, 60, 90
176 static int lcd_sleep_timeout = 10*HZ;
177 #else
178 /* Target defines needed value */
179 #define lcd_sleep_timeout LCD_SLEEP_TIMEOUT
180 #endif
182 static int lcd_sleep_timer SHAREDDATA_ATTR = 0;
184 static void backlight_lcd_sleep_countdown(bool start)
186 if (!start)
188 /* Cancel the LCD sleep countdown */
189 lcd_sleep_timer = 0;
190 return;
193 /* Start LCD sleep countdown */
194 if (lcd_sleep_timeout < 0)
196 lcd_sleep_timer = 0; /* Setting == Always */
197 /* Ensure lcd_sleep() is called from backlight_thread() */
198 #if (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_PWM)
199 queue_post(&backlight_queue, LCD_SLEEP, 0);
200 #else
201 lcd_sleep();
202 #endif
204 else
206 lcd_sleep_timer = lcd_sleep_timeout;
209 #endif /* HAVE_LCD_SLEEP */
211 #if (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_SETTING) \
212 || (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_HW_REG)
213 static int backlight_fading_type = (FADING_UP|FADING_DOWN);
214 static int backlight_fading_state = NOT_FADING;
215 #endif
218 /* backlight fading */
219 #if (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_PWM)
220 #define BL_PWM_INTERVAL 5 /* Cycle interval in ms */
221 #define BL_PWM_BITS 8
222 #define BL_PWM_COUNT (1<<BL_PWM_BITS)
224 /* s15.16 fixed point variables */
225 static int32_t bl_fade_in_step = ((BL_PWM_INTERVAL*BL_PWM_COUNT)<<16)/300;
226 static int32_t bl_fade_out_step = ((BL_PWM_INTERVAL*BL_PWM_COUNT)<<16)/2000;
227 static int32_t bl_dim_fraction = 0;
229 static int bl_dim_target = 0;
230 static int bl_dim_current = 0;
231 static enum {DIM_STATE_START, DIM_STATE_MAIN} bl_dim_state = DIM_STATE_START;
232 static bool bl_timer_active = false;
234 static void backlight_isr(void)
236 int timer_period = (TIMER_FREQ*BL_PWM_INTERVAL/1000);
237 bool idle = false;
239 switch (bl_dim_state)
241 /* New cycle */
242 case DIM_STATE_START:
243 bl_dim_current = bl_dim_fraction >> 16;
245 if (bl_dim_current > 0 && bl_dim_current < BL_PWM_COUNT)
247 _backlight_on_isr();
248 timer_period = (timer_period * bl_dim_current) >> BL_PWM_BITS;
249 bl_dim_state = DIM_STATE_MAIN;
251 else
253 if (bl_dim_current)
254 _backlight_on_isr();
255 else
256 _backlight_off_isr();
257 if (bl_dim_current == bl_dim_target)
258 idle = true;
260 if (bl_dim_current < bl_dim_target)
262 bl_dim_fraction = MIN(bl_dim_fraction + bl_fade_in_step,
263 (BL_PWM_COUNT<<16));
265 else if (bl_dim_current > bl_dim_target)
267 bl_dim_fraction = MAX(bl_dim_fraction - bl_fade_out_step, 0);
269 break;
271 /* Dim main screen */
272 case DIM_STATE_MAIN:
273 _backlight_off_isr();
274 timer_period = (timer_period * (BL_PWM_COUNT - bl_dim_current))
275 >> BL_PWM_BITS;
276 bl_dim_state = DIM_STATE_START;
277 break ;
279 if (idle)
281 #if defined(_BACKLIGHT_FADE_BOOST) || defined(_BACKLIGHT_FADE_ENABLE)
282 queue_post(&backlight_queue, BACKLIGHT_FADE_FINISH, 0);
283 #endif
284 timer_unregister();
285 bl_timer_active = false;
287 #ifdef HAVE_LCD_SLEEP
288 if (bl_dim_current == 0)
289 backlight_lcd_sleep_countdown(true);
290 #endif
292 else
293 timer_set_period(timer_period);
296 static void backlight_switch(void)
298 if (bl_dim_target > (BL_PWM_COUNT/2))
300 _backlight_on_normal();
301 bl_dim_fraction = (BL_PWM_COUNT<<16);
303 else
305 _backlight_off_normal();
306 bl_dim_fraction = 0;
308 #ifdef HAVE_LCD_SLEEP
309 backlight_lcd_sleep_countdown(true);
310 #endif
314 static void backlight_release_timer(void)
316 #ifdef _BACKLIGHT_FADE_BOOST
317 cpu_boost(false);
318 #endif
319 timer_unregister();
320 bl_timer_active = false;
321 backlight_switch();
324 static void backlight_dim(int value)
326 /* protect from extraneous calls with the same target value */
327 if (value == bl_dim_target)
328 return;
330 bl_dim_target = value;
332 if (bl_timer_active)
333 return ;
335 if (timer_register(0, backlight_release_timer, 2, backlight_isr
336 IF_COP(, CPU)))
338 #ifdef _BACKLIGHT_FADE_BOOST
339 /* Prevent cpu frequency changes while dimming. */
340 cpu_boost(true);
341 #endif
342 bl_timer_active = true;
344 else
345 backlight_switch();
348 static void backlight_setup_fade_up(void)
350 if (bl_fade_in_step > 0)
352 #ifdef _BACKLIGHT_FADE_ENABLE
353 _backlight_hw_enable(true);
354 #endif
355 backlight_dim(BL_PWM_COUNT);
357 else
359 bl_dim_target = BL_PWM_COUNT;
360 bl_dim_fraction = (BL_PWM_COUNT<<16);
361 _backlight_on_normal();
365 static void backlight_setup_fade_down(void)
367 if (bl_fade_out_step > 0)
369 backlight_dim(0);
371 else
373 bl_dim_target = bl_dim_fraction = 0;
374 _backlight_off_normal();
375 #ifdef HAVE_LCD_SLEEP
376 backlight_lcd_sleep_countdown(true);
377 #endif
381 void backlight_set_fade_in(int value)
383 if (value > 0)
384 bl_fade_in_step = ((BL_PWM_INTERVAL*BL_PWM_COUNT)<<16) / value;
385 else
386 bl_fade_in_step = 0;
389 void backlight_set_fade_out(int value)
391 if (value > 0)
392 bl_fade_out_step = ((BL_PWM_INTERVAL*BL_PWM_COUNT)<<16) / value;
393 else
394 bl_fade_out_step = 0;
397 #elif (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_SETTING) \
398 || (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_HW_REG)
400 void backlight_set_fade_out(bool value)
402 if(value) /* on */
403 backlight_fading_type |= FADING_DOWN;
404 else
405 backlight_fading_type &= FADING_UP;
408 void backlight_set_fade_in(bool value)
410 if(value) /* on */
411 backlight_fading_type |= FADING_UP;
412 else
413 backlight_fading_type &= FADING_DOWN;
416 static void backlight_setup_fade_up(void)
418 if (backlight_fading_type & FADING_UP)
420 if (backlight_fading_state == NOT_FADING)
422 /* make sure the backlight is at lowest level */
423 _backlight_on();
425 backlight_fading_state = FADING_UP;
427 else
429 backlight_fading_state = NOT_FADING;
430 _backlight_fade_update_state(backlight_brightness);
431 _backlight_on();
432 _backlight_set_brightness(backlight_brightness);
436 static void backlight_setup_fade_down(void)
438 if (backlight_fading_type & FADING_DOWN)
440 backlight_fading_state = FADING_DOWN;
442 else
444 backlight_fading_state = NOT_FADING;
445 _backlight_fade_update_state(MIN_BRIGHTNESS_SETTING-1);
446 _backlight_off();
447 #if (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_HW_REG)
448 /* write the lowest brightness level to the hardware so that
449 * fading up is glitch free */
450 _backlight_set_brightness(MIN_BRIGHTNESS_SETTING);
451 #endif
452 #ifdef HAVE_LCD_SLEEP
453 backlight_lcd_sleep_countdown(true);
454 #endif
457 #endif /* CONFIG_BACKLIGHT_FADING */
459 static inline void do_backlight_off(void)
461 backlight_timer = 0;
462 #if BACKLIGHT_FADE_IN_THREAD
463 backlight_setup_fade_down();
464 #else
465 _backlight_off();
466 /* targets that have fading need to start the countdown when done with
467 * fading */
468 #ifdef HAVE_LCD_SLEEP
469 backlight_lcd_sleep_countdown(true);
470 #endif
471 #endif
474 /* Update state of backlight according to timeout setting */
475 static void backlight_update_state(void)
478 int timeout = backlight_get_current_timeout();
480 /* Backlight == OFF in the setting? */
481 if (UNLIKELY(timeout < 0))
483 do_backlight_off();
484 #if (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_SETTING) \
485 || (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_HW_REG)
486 /* necessary step to issue fading down when the setting is selected */
487 if (queue_empty(&backlight_queue))
488 queue_post(&backlight_queue, SYS_TIMEOUT, 0);
489 #endif
491 else
493 backlight_timer = timeout;
495 #ifdef HAVE_LCD_SLEEP
496 backlight_lcd_sleep_countdown(false); /* wake up lcd */
497 #endif
499 #if BACKLIGHT_FADE_IN_THREAD
500 backlight_setup_fade_up();
501 #else
502 _backlight_on();
503 #endif
507 #ifdef HAVE_REMOTE_LCD
508 /* Update state of remote backlight according to timeout setting */
509 static void remote_backlight_update_state(void)
511 int timeout = remote_backlight_get_current_timeout();
512 /* Backlight == OFF in the setting? */
513 if (timeout < 0)
515 remote_backlight_timer = 0; /* Disable the timeout */
516 _remote_backlight_off();
518 else
520 remote_backlight_timer = timeout;
521 _remote_backlight_on();
524 #endif /* HAVE_REMOTE_LCD */
526 void backlight_thread(void)
528 struct queue_event ev;
529 bool locked = false;
531 while(1)
533 #if (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_SETTING) \
534 || (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_HW_REG)
535 if (backlight_fading_state != NOT_FADING)
536 queue_wait_w_tmo(&backlight_queue, &ev, FADE_DELAY);
537 else
538 #endif
539 queue_wait_w_tmo(&backlight_queue, &ev, BACKLIGHT_THREAD_TIMEOUT);
540 switch(ev.id)
541 { /* These events must always be processed */
542 #ifdef _BACKLIGHT_FADE_BOOST
543 case BACKLIGHT_FADE_FINISH:
544 cpu_boost(false);
545 break;
546 #endif
547 #ifdef _BACKLIGHT_FADE_ENABLE
548 case BACKLIGHT_FADE_FINISH:
549 _backlight_hw_enable((bl_dim_current|bl_dim_target) != 0);
550 break;
551 #endif
553 #ifndef SIMULATOR
554 /* Here for now or else the aggressive init messes up scrolling */
555 #ifdef HAVE_REMOTE_LCD
556 case SYS_REMOTE_PLUGGED:
557 lcd_remote_on();
558 lcd_remote_update();
559 break;
561 case SYS_REMOTE_UNPLUGGED:
562 lcd_remote_off();
563 break;
564 #elif defined HAVE_REMOTE_LCD_AS_MAIN
565 case SYS_REMOTE_PLUGGED:
566 lcd_on();
567 lcd_update();
568 break;
570 case SYS_REMOTE_UNPLUGGED:
571 lcd_off();
572 break;
573 #endif /* HAVE_REMOTE_LCD/ HAVE_REMOTE_LCD_AS_MAIN */
574 #endif /* !SIMULATOR */
575 case SYS_USB_CONNECTED:
576 usb_acknowledge(SYS_USB_CONNECTED_ACK);
577 break;
579 case SYS_USB_DISCONNECTED:
580 usb_acknowledge(SYS_USB_DISCONNECTED_ACK);
581 break;
583 #ifdef BACKLIGHT_DRIVER_CLOSE
584 /* Get out of here */
585 case BACKLIGHT_QUIT:
586 return;
587 #endif
589 if (locked)
590 continue;
592 switch(ev.id)
593 { /* These events are only processed if backlight isn't locked */
594 #ifdef HAVE_REMOTE_LCD
595 case REMOTE_BACKLIGHT_TMO_CHANGED:
596 case REMOTE_BACKLIGHT_ON:
597 remote_backlight_update_state();
598 break;
600 case REMOTE_BACKLIGHT_OFF:
601 remote_backlight_timer = 0; /* Disable the timeout */
602 _remote_backlight_off();
603 break;
604 #endif /* HAVE_REMOTE_LCD */
606 case BACKLIGHT_TMO_CHANGED:
607 case BACKLIGHT_ON:
608 backlight_update_state();
609 break;
611 case BACKLIGHT_OFF:
612 do_backlight_off();
613 break;
614 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
615 case BACKLIGHT_BRIGHTNESS_CHANGED:
616 backlight_brightness = (int)ev.data;
617 _backlight_set_brightness((int)ev.data);
618 #if (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_SETTING) \
619 || (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_HW_REG)
620 /* receive backlight brightness */
621 _backlight_fade_update_state((int)ev.data);
622 #endif
623 break;
624 #endif /* HAVE_BACKLIGHT_BRIGHTNESS */
625 #ifdef HAVE_LCD_SLEEP
626 case LCD_SLEEP:
627 lcd_sleep();
628 break;
629 #endif
630 #ifdef HAVE_BUTTON_LIGHT
631 case BUTTON_LIGHT_TMO_CHANGED:
632 case BUTTON_LIGHT_ON:
633 buttonlight_update_state();
634 break;
636 case BUTTON_LIGHT_OFF:
637 buttonlight_timer = 0;
638 _buttonlight_off();
639 break;
640 #ifdef HAVE_BUTTONLIGHT_BRIGHTNESS
641 case BUTTON_LIGHT_BRIGHTNESS_CHANGED:
642 _buttonlight_set_brightness((int)ev.data);
643 break;
644 #endif /* HAVE_BUTTONLIGHT_BRIGHTNESS */
645 #endif /* HAVE_BUTTON_LIGHT */
647 case SYS_POWEROFF: /* Lock backlight on poweroff so it doesn't */
648 locked = true; /* go off before power is actually cut. */
649 /* fall through */
650 #if CONFIG_CHARGING
651 case SYS_CHARGER_CONNECTED:
652 case SYS_CHARGER_DISCONNECTED:
653 #endif
654 backlight_update_state();
655 #ifdef HAVE_REMOTE_LCD
656 remote_backlight_update_state();
657 #endif
658 break;
659 case SYS_TIMEOUT:
660 #if (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_SETTING) \
661 || (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_HW_REG)
662 if (backlight_fading_state != NOT_FADING)
664 if ((_backlight_fade_step(backlight_fading_state)))
665 { /* finished fading */
666 #ifdef HAVE_LCD_SLEEP
667 if (backlight_fading_state == FADING_DOWN)
668 { /* start sleep countdown */
669 backlight_lcd_sleep_countdown(true);
671 #endif
672 backlight_fading_state = NOT_FADING;
675 else
676 #endif /* CONFIG_BACKLIGHT_FADING */
677 backlight_timeout_handler();
678 break;
680 } /* end while */
683 static void backlight_timeout_handler(void)
685 if(backlight_timer > 0)
687 backlight_timer -= BACKLIGHT_THREAD_TIMEOUT;
688 if(backlight_timer <= 0)
690 do_backlight_off();
693 #ifdef HAVE_LCD_SLEEP
694 else if(lcd_sleep_timer > 0)
696 lcd_sleep_timer -= BACKLIGHT_THREAD_TIMEOUT;
697 if(lcd_sleep_timer <= 0)
699 lcd_sleep();
702 #endif /* HAVE_LCD_SLEEP */
703 #ifdef HAVE_REMOTE_LCD
704 if(remote_backlight_timer > 0)
706 remote_backlight_timer -= BACKLIGHT_THREAD_TIMEOUT;
707 if(remote_backlight_timer <= 0)
709 _remote_backlight_off();
712 #endif /* HAVE_REMOVE_LCD */
713 #ifdef HAVE_BUTTON_LIGHT
714 if (buttonlight_timer > 0)
716 buttonlight_timer -= BACKLIGHT_THREAD_TIMEOUT;
717 if (buttonlight_timer <= 0)
719 _buttonlight_off();
722 #endif /* HAVE_BUTTON_LIGHT */
725 void backlight_init(void)
727 queue_init(&backlight_queue, true);
729 if (_backlight_init())
731 #if (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_PWM)
732 /* If backlight is already on, don't fade in. */
733 bl_dim_target = BL_PWM_COUNT;
734 bl_dim_fraction = (BL_PWM_COUNT<<16);
735 #endif
737 /* Leave all lights as set by the bootloader here. The settings load will
738 * call the appropriate backlight_set_*() functions, only changing light
739 * status if necessary. */
740 #ifdef BACKLIGHT_DRIVER_CLOSE
741 backlight_thread_id =
742 #endif
743 create_thread(backlight_thread, backlight_stack,
744 sizeof(backlight_stack), 0, backlight_thread_name
745 IF_PRIO(, PRIORITY_USER_INTERFACE)
746 IF_COP(, CPU));
749 #ifdef BACKLIGHT_DRIVER_CLOSE
750 void backlight_close(void)
752 unsigned int thread = backlight_thread_id;
754 /* Wait for thread to exit */
755 if (thread == 0)
756 return;
758 backlight_thread_id = 0;
760 queue_post(&backlight_queue, BACKLIGHT_QUIT, 0);
761 thread_wait(thread);
763 #endif /* BACKLIGHT_DRIVER_CLOSE */
765 void backlight_on(void)
767 queue_remove_from_head(&backlight_queue, BACKLIGHT_ON);
768 queue_post(&backlight_queue, BACKLIGHT_ON, 0);
771 void backlight_off(void)
773 queue_post(&backlight_queue, BACKLIGHT_OFF, 0);
776 /* returns true when the backlight is on,
777 * and optionally when it's set to always off. */
778 bool is_backlight_on(bool ignore_always_off)
780 int timeout = backlight_get_current_timeout();
781 return (backlight_timer > 0) /* countdown */
782 || (timeout == 0) /* always on */
783 || ((timeout < 0) && !ignore_always_off);
786 /* return value in ticks; 0 means always on, <0 means always off */
787 int backlight_get_current_timeout(void)
789 #ifdef HAS_BUTTON_HOLD
790 if ((backlight_on_button_hold != 0)
791 #ifdef HAVE_REMOTE_LCD_AS_MAIN
792 && remote_button_hold()
793 #else
794 && button_hold()
795 #endif
797 return (backlight_on_button_hold == 2) ? 0 : -1;
798 /* always on or always off */
799 else
800 #endif
801 #if CONFIG_CHARGING
802 if (power_input_present())
803 return backlight_timeout_plugged;
804 else
805 #endif
806 return backlight_timeout_normal;
809 void backlight_set_timeout(int value)
811 backlight_timeout_normal = HZ * value;
812 queue_post(&backlight_queue, BACKLIGHT_TMO_CHANGED, 0);
815 #if CONFIG_CHARGING
816 void backlight_set_timeout_plugged(int value)
818 backlight_timeout_plugged = HZ * value;
819 queue_post(&backlight_queue, BACKLIGHT_TMO_CHANGED, 0);
821 #endif /* CONFIG_CHARGING */
823 #ifdef HAS_BUTTON_HOLD
824 /* Hold button change event handler. */
825 void backlight_hold_changed(bool hold_button)
827 if (!hold_button || (backlight_on_button_hold > 0))
828 /* if unlocked or override in effect */
829 backlight_on();
832 void backlight_set_on_button_hold(int index)
834 if ((unsigned)index >= 3)
835 /* if given a weird value, use default */
836 index = 0;
838 backlight_on_button_hold = index;
839 queue_post(&backlight_queue, BACKLIGHT_TMO_CHANGED, 0);
841 #endif /* HAS_BUTTON_HOLD */
843 #ifdef HAVE_LCD_SLEEP_SETTING
844 void lcd_set_sleep_after_backlight_off(int index)
846 if ((unsigned)index >= sizeof(lcd_sleep_timeout_value))
847 /* if given a weird value, use default */
848 index = 3;
850 lcd_sleep_timeout = HZ * lcd_sleep_timeout_value[index];
852 if (is_backlight_on(true))
853 /* Timer will be set when bl turns off or bl set to on. */
854 return;
856 /* Backlight is Off */
857 if (lcd_sleep_timeout < 0)
858 lcd_sleep_timer = 1; /* Always - sleep next tick */
859 else
860 lcd_sleep_timer = lcd_sleep_timeout; /* Never, other */
862 #endif /* HAVE_LCD_SLEEP_SETTING */
864 #ifdef HAVE_REMOTE_LCD
865 void remote_backlight_on(void)
867 queue_post(&backlight_queue, REMOTE_BACKLIGHT_ON, 0);
870 void remote_backlight_off(void)
872 queue_post(&backlight_queue, REMOTE_BACKLIGHT_OFF, 0);
875 void remote_backlight_set_timeout(int value)
877 remote_backlight_timeout_normal = HZ * value;
878 queue_post(&backlight_queue, REMOTE_BACKLIGHT_TMO_CHANGED, 0);
881 #if CONFIG_CHARGING
882 void remote_backlight_set_timeout_plugged(int value)
884 remote_backlight_timeout_plugged = HZ * value;
885 queue_post(&backlight_queue, REMOTE_BACKLIGHT_TMO_CHANGED, 0);
887 #endif /* CONFIG_CHARGING */
889 #ifdef HAS_REMOTE_BUTTON_HOLD
890 /* Remote hold button change event handler. */
891 void remote_backlight_hold_changed(bool rc_hold_button)
893 if (!rc_hold_button || (remote_backlight_on_button_hold > 0))
894 /* if unlocked or override */
895 remote_backlight_on();
898 void remote_backlight_set_on_button_hold(int index)
900 if ((unsigned)index >= 3)
901 /* if given a weird value, use default */
902 index = 0;
904 remote_backlight_on_button_hold = index;
905 queue_post(&backlight_queue, REMOTE_BACKLIGHT_TMO_CHANGED, 0);
907 #endif /* HAS_REMOTE_BUTTON_HOLD */
909 /* return value in ticks; 0 means always on, <0 means always off */
910 int remote_backlight_get_current_timeout(void)
912 #ifdef HAS_REMOTE_BUTTON_HOLD
913 if (remote_button_hold() && (remote_backlight_on_button_hold != 0))
914 return (remote_backlight_on_button_hold == 2)
915 ? 0 : -1; /* always on or always off */
916 else
917 #endif
918 #if CONFIG_CHARGING
919 if (power_input_present())
920 return remote_backlight_timeout_plugged;
921 else
922 #endif
923 return remote_backlight_timeout_normal;
926 /* returns true when the backlight is on, and
927 * optionally when it's set to always off */
928 bool is_remote_backlight_on(bool ignore_always_off)
930 int timeout = remote_backlight_get_current_timeout();
931 return (remote_backlight_timer > 0) /* countdown */
932 || (timeout == 0) /* always on */
933 || ((timeout < 0) && !ignore_always_off);
936 #endif /* HAVE_REMOTE_LCD */
938 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
939 void backlight_set_brightness(int val)
941 if (val < MIN_BRIGHTNESS_SETTING)
942 val = MIN_BRIGHTNESS_SETTING;
943 else if (val > MAX_BRIGHTNESS_SETTING)
944 val = MAX_BRIGHTNESS_SETTING;
946 queue_post(&backlight_queue, BACKLIGHT_BRIGHTNESS_CHANGED, val);
948 #endif /* HAVE_BACKLIGHT_BRIGHTNESS */
950 #ifdef HAVE_BUTTONLIGHT_BRIGHTNESS
951 void buttonlight_set_brightness(int val)
953 if (val < MIN_BRIGHTNESS_SETTING)
954 val = MIN_BRIGHTNESS_SETTING;
955 else if (val > MAX_BRIGHTNESS_SETTING)
956 val = MAX_BRIGHTNESS_SETTING;
958 queue_post(&backlight_queue, BUTTON_LIGHT_BRIGHTNESS_CHANGED, val);
960 #endif /* HAVE_BUTTONLIGHT_BRIGHTNESS */
962 #else /* !defined(HAVE_BACKLIGHT) || !defined(BACKLIGHT_FULL_INIT)
963 -- no backlight, empty dummy functions */
965 #if defined(HAVE_BACKLIGHT) && !defined(BACKLIGHT_FULL_INIT)
966 void backlight_init(void)
968 (void)_backlight_init();
969 _backlight_on();
971 #endif
973 void backlight_on(void) {}
974 void backlight_off(void) {}
975 void buttonlight_on(void) {}
976 void backlight_set_timeout(int value) {(void)value;}
978 bool is_backlight_on(bool ignore_always_off)
980 (void)ignore_always_off;
981 return true;
983 #ifdef HAVE_REMOTE_LCD
984 void remote_backlight_on(void) {}
985 void remote_backlight_off(void) {}
986 void remote_backlight_set_timeout(int value) {(void)value;}
988 bool is_remote_backlight_on(bool ignore_always_off)
990 (void)ignore_always_off;
991 return true;
993 #endif /* HAVE_REMOTE_LCD */
994 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
995 void backlight_set_brightness(int val) { (void)val; }
996 #endif
997 #ifdef HAVE_BUTTONLIGHT_BRIGHTNESS
998 void buttonlight_set_brightness(int val) { (void)val; }
999 #endif
1000 #endif /* defined(HAVE_BACKLIGHT) && defined(BACKLIGHT_FULL_INIT) */