A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 1080 lines 29 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2002 by Linus Nielsen Feltzing 11 * Additional work by Martin Ritter (2007) and Thomas Martitz (2008) 12 * for backlight thread fading 13 * 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. 18 * 19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 20 * KIND, either express or implied. 21 * 22 ****************************************************************************/ 23#include "config.h" 24#if !defined(BOOTLOADER) 25#include "settings.h" 26#include "action.h" 27#endif 28#include <stdlib.h> 29#include "cpu.h" 30#include "kernel.h" 31#include "thread.h" 32#include "i2c.h" 33#include "debug.h" 34#include "rtc.h" 35#include "usb.h" 36#include "power.h" 37#include "system.h" 38#include "button.h" 39#include "timer.h" 40#include "backlight.h" 41#include "lcd.h" 42#include "screendump.h" 43 44#ifdef HAVE_REMOTE_LCD 45#include "lcd-remote.h" 46#endif 47 48#ifndef SIMULATOR 49/* 50 Device specific implementation: 51 bool backlight_hw_init(void); 52 void backlight_hw_on(void); 53 void backlight_hw_off(void); 54 void backlight_hw_brightness(int brightness); 55*/ 56#include "backlight-target.h" 57#else 58#include "backlight-sim.h" 59#endif 60 61#if defined(HAVE_BACKLIGHT) && defined(BACKLIGHT_FULL_INIT) 62 63#if (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_SETTING) \ 64 || (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_HW_REG) 65#include "backlight-sw-fading.h" 66#endif 67 68#define BACKLIGHT_FADE_IN_THREAD \ 69 (CONFIG_BACKLIGHT_FADING & (BACKLIGHT_FADING_SW_SETTING \ 70 |BACKLIGHT_FADING_SW_HW_REG \ 71 |BACKLIGHT_FADING_PWM) ) 72 73#define BACKLIGHT_THREAD_TIMEOUT HZ 74 75enum { 76 BACKLIGHT_ON, 77 BACKLIGHT_OFF, 78 BACKLIGHT_TMO_CHANGED, 79#ifdef HAVE_BACKLIGHT_BRIGHTNESS 80 BACKLIGHT_BRIGHTNESS_CHANGED, 81#endif 82#ifdef HAVE_REMOTE_LCD 83 REMOTE_BACKLIGHT_ON, 84 REMOTE_BACKLIGHT_OFF, 85 REMOTE_BACKLIGHT_TMO_CHANGED, 86#endif 87#if defined(_BACKLIGHT_FADE_BOOST) || defined(_BACKLIGHT_FADE_ENABLE) 88 BACKLIGHT_FADE_FINISH, 89#endif 90#ifdef HAVE_LCD_SLEEP 91 LCD_SLEEP, 92#endif 93#ifdef HAVE_BUTTON_LIGHT 94 BUTTON_LIGHT_ON, 95 BUTTON_LIGHT_OFF, 96 BUTTON_LIGHT_TMO_CHANGED, 97#ifdef HAVE_BUTTONLIGHT_BRIGHTNESS 98 BUTTON_LIGHT_BRIGHTNESS_CHANGED, 99#endif 100#endif /* HAVE_BUTTON_LIGHT */ 101#ifdef BACKLIGHT_DRIVER_CLOSE 102 BACKLIGHT_QUIT, 103#endif 104}; 105 106static void backlight_thread(void); 107static long backlight_stack[DEFAULT_STACK_SIZE/sizeof(long)]; 108static const char backlight_thread_name[] = "backlight"; 109static struct event_queue backlight_queue SHAREDBSS_ATTR; 110static bool ignore_backlight_on = false; 111static int backlight_ignored_timer = 0; 112#ifdef BACKLIGHT_DRIVER_CLOSE 113static unsigned int backlight_thread_id = 0; 114#endif 115 116#ifdef HAVE_BACKLIGHT_BRIGHTNESS 117int backlight_brightness = DEFAULT_BRIGHTNESS_SETTING; 118#endif 119static int backlight_timer SHAREDBSS_ATTR; 120static int backlight_timeout_normal = 5*HZ; 121#if CONFIG_CHARGING 122static int backlight_timeout_plugged = 5*HZ; 123#endif 124static int backlight_on_button_hold = 0; 125static void backlight_handle_timeout(void); 126 127#ifdef HAVE_BUTTON_LIGHT 128static int buttonlight_timer; 129static int buttonlight_timeout = 5*HZ; 130static bool ignore_buttonlight_on = false; 131static int buttonlight_ignored_timer = 0; 132 133/* Update state of buttonlight according to timeout setting */ 134static void buttonlight_update_state(void) 135{ 136 buttonlight_timer = buttonlight_timeout; 137 138 /* Buttonlight == OFF in the setting? */ 139 if (buttonlight_timer < 0) 140 { 141 buttonlight_timer = 0; /* Disable the timeout */ 142 buttonlight_hw_off(); 143 } 144 else 145 buttonlight_hw_on(); 146} 147 148/* external interface */ 149 150void buttonlight_on(void) 151{ 152 if(!ignore_buttonlight_on) 153 { 154 queue_remove_from_head(&backlight_queue, BUTTON_LIGHT_ON); 155 queue_post(&backlight_queue, BUTTON_LIGHT_ON, 0); 156 } 157} 158 159void buttonlight_on_ignore(bool value, int timeout) 160{ 161 ignore_buttonlight_on = value; 162 buttonlight_ignored_timer = timeout; 163} 164 165void buttonlight_off(void) 166{ 167 queue_post(&backlight_queue, BUTTON_LIGHT_OFF, 0); 168} 169 170void buttonlight_set_timeout(int value) 171{ 172 buttonlight_timeout = HZ * value; 173 queue_post(&backlight_queue, BUTTON_LIGHT_TMO_CHANGED, 0); 174} 175 176int buttonlight_get_current_timeout(void) 177{ 178 return buttonlight_timeout; 179} 180 181#endif /* HAVE_BUTTON_LIGHT */ 182 183#ifdef HAVE_REMOTE_LCD 184static int remote_backlight_timer; 185static int remote_backlight_timeout_normal = 5*HZ; 186#if CONFIG_CHARGING 187static int remote_backlight_timeout_plugged = 5*HZ; 188#endif 189#ifdef HAS_REMOTE_BUTTON_HOLD 190static int remote_backlight_on_button_hold = 0; 191#endif 192#endif /* HAVE_REMOTE_LCD */ 193 194#ifdef HAVE_LCD_SLEEP 195#ifdef HAVE_LCD_SLEEP_SETTING 196static int lcd_sleep_timeout = 10*HZ; 197#else 198/* Target defines needed value */ 199#define lcd_sleep_timeout LCD_SLEEP_TIMEOUT 200#endif 201 202static int lcd_sleep_timer SHAREDDATA_ATTR = 0; 203 204static void backlight_lcd_sleep_countdown(bool start) 205{ 206 if (!start) 207 { 208 /* Cancel the LCD sleep countdown */ 209 lcd_sleep_timer = 0; 210 return; 211 } 212 213 /* Start LCD sleep countdown */ 214 if (lcd_sleep_timeout <= 0) 215 { 216 lcd_sleep_timer = 0; 217 if (lcd_sleep_timeout == 0) /* Setting == Always */ 218 { 219 /* Ensure lcd_sleep() is called from backlight_thread() */ 220#if (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_PWM) 221 queue_post(&backlight_queue, LCD_SLEEP, 0); 222#else 223 lcd_sleep(); 224#endif 225 } 226 } 227 else 228 { 229 lcd_sleep_timer = lcd_sleep_timeout; 230 } 231} 232#endif /* HAVE_LCD_SLEEP */ 233 234#if (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_SETTING) \ 235 || (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_HW_REG) 236static int backlight_fading_type = (FADING_UP|FADING_DOWN); 237static int backlight_fading_state = NOT_FADING; 238#endif 239 240 241/* backlight fading */ 242#if (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_PWM) 243#define BL_PWM_INTERVAL 5 /* Cycle interval in ms */ 244#define BL_PWM_BITS 8 245#define BL_PWM_COUNT (1<<BL_PWM_BITS) 246 247/* s15.16 fixed point variables */ 248static int32_t bl_fade_in_step = ((BL_PWM_INTERVAL*BL_PWM_COUNT)<<16)/300; 249static int32_t bl_fade_out_step = ((BL_PWM_INTERVAL*BL_PWM_COUNT)<<16)/2000; 250static int32_t bl_dim_fraction = 0; 251 252static int bl_dim_target = 0; 253static int bl_dim_current = 0; 254static enum {DIM_STATE_START, DIM_STATE_MAIN} bl_dim_state = DIM_STATE_START; 255static bool bl_timer_active = false; 256 257static void backlight_isr(void) 258{ 259 int timer_period = (TIMER_FREQ*BL_PWM_INTERVAL/1000); 260 bool idle = false; 261 262 switch (bl_dim_state) 263 { 264 /* New cycle */ 265 case DIM_STATE_START: 266 bl_dim_current = bl_dim_fraction >> 16; 267 268 if (bl_dim_current > 0 && bl_dim_current < BL_PWM_COUNT) 269 { 270 _backlight_on_isr(); 271 timer_period = (timer_period * bl_dim_current) >> BL_PWM_BITS; 272 bl_dim_state = DIM_STATE_MAIN; 273 } 274 else 275 { 276 if (bl_dim_current) 277 _backlight_on_isr(); 278 else 279 _backlight_off_isr(); 280 if (bl_dim_current == bl_dim_target) 281 idle = true; 282 } 283 if (bl_dim_current < bl_dim_target) 284 { 285 bl_dim_fraction = MIN(bl_dim_fraction + bl_fade_in_step, 286 (BL_PWM_COUNT<<16)); 287 } 288 else if (bl_dim_current > bl_dim_target) 289 { 290 bl_dim_fraction = MAX(bl_dim_fraction - bl_fade_out_step, 0); 291 } 292 break; 293 294 /* Dim main screen */ 295 case DIM_STATE_MAIN: 296 _backlight_off_isr(); 297 timer_period = (timer_period * (BL_PWM_COUNT - bl_dim_current)) 298 >> BL_PWM_BITS; 299 bl_dim_state = DIM_STATE_START; 300 break ; 301 } 302 if (idle) 303 { 304#if defined(_BACKLIGHT_FADE_BOOST) || defined(_BACKLIGHT_FADE_ENABLE) 305 queue_post(&backlight_queue, BACKLIGHT_FADE_FINISH, 0); 306#endif 307 timer_unregister(); 308 bl_timer_active = false; 309 310#ifdef HAVE_LCD_SLEEP 311 if (bl_dim_current == 0) 312 backlight_lcd_sleep_countdown(true); 313#endif 314 } 315 else 316 timer_set_period(timer_period); 317} 318 319static void backlight_switch(void) 320{ 321 if (bl_dim_target > (BL_PWM_COUNT/2)) 322 { 323 _backlight_on_normal(); 324 bl_dim_fraction = (BL_PWM_COUNT<<16); 325 } 326 else 327 { 328 _backlight_off_normal(); 329 bl_dim_fraction = 0; 330 331#ifdef HAVE_LCD_SLEEP 332 backlight_lcd_sleep_countdown(true); 333#endif 334 } 335} 336 337static void backlight_release_timer(void) 338{ 339#ifdef _BACKLIGHT_FADE_BOOST 340 cpu_boost(false); 341#endif 342 timer_unregister(); 343 bl_timer_active = false; 344 backlight_switch(); 345} 346 347static void backlight_dim(int value) 348{ 349 /* protect from extraneous calls with the same target value */ 350 if (value == bl_dim_target) 351 return; 352 353 bl_dim_target = value; 354 355 if (bl_timer_active) 356 return ; 357 358 if (timer_register(0, backlight_release_timer, 2, backlight_isr 359 IF_COP(, CPU))) 360 { 361#ifdef _BACKLIGHT_FADE_BOOST 362 /* Prevent cpu frequency changes while dimming. */ 363 cpu_boost(true); 364#endif 365 bl_timer_active = true; 366 } 367 else 368 backlight_switch(); 369} 370 371static void backlight_setup_fade_up(void) 372{ 373 if (bl_fade_in_step > 0) 374 { 375#ifdef _BACKLIGHT_FADE_ENABLE 376 _backlight_hw_enable(true); 377#endif 378 backlight_dim(BL_PWM_COUNT); 379 } 380 else 381 { 382 bl_dim_target = BL_PWM_COUNT; 383 bl_dim_fraction = (BL_PWM_COUNT<<16); 384 _backlight_on_normal(); 385 } 386} 387 388static void backlight_setup_fade_down(void) 389{ 390 if (bl_fade_out_step > 0) 391 { 392 backlight_dim(0); 393 } 394 else 395 { 396 bl_dim_target = bl_dim_fraction = 0; 397 _backlight_off_normal(); 398#ifdef HAVE_LCD_SLEEP 399 backlight_lcd_sleep_countdown(true); 400#endif 401 } 402} 403 404void backlight_set_fade_in(int value) 405{ 406 if (value > 0) 407 bl_fade_in_step = ((BL_PWM_INTERVAL*BL_PWM_COUNT)<<16) / value; 408 else 409 bl_fade_in_step = 0; 410} 411 412void backlight_set_fade_out(int value) 413{ 414 if (value > 0) 415 bl_fade_out_step = ((BL_PWM_INTERVAL*BL_PWM_COUNT)<<16) / value; 416 else 417 bl_fade_out_step = 0; 418} 419 420#elif (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_SETTING) \ 421 || (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_HW_REG) 422 423void backlight_set_fade_out(bool value) 424{ 425 if(value) /* on */ 426 backlight_fading_type |= FADING_DOWN; 427 else 428 backlight_fading_type &= FADING_UP; 429} 430 431void backlight_set_fade_in(bool value) 432{ 433 if(value) /* on */ 434 backlight_fading_type |= FADING_UP; 435 else 436 backlight_fading_type &= FADING_DOWN; 437} 438 439static void backlight_setup_fade_up(void) 440{ 441 if (backlight_fading_type & FADING_UP) 442 { 443 if (backlight_fading_state == NOT_FADING) 444 { 445 /* make sure the backlight is at lowest level */ 446 backlight_hw_on(); 447 } 448 backlight_fading_state = FADING_UP; 449 } 450 else 451 { 452 backlight_fading_state = NOT_FADING; 453 _backlight_fade_update_state(backlight_brightness); 454 backlight_hw_on(); 455 backlight_hw_brightness(backlight_brightness); 456 } 457} 458 459static void backlight_setup_fade_down(void) 460{ 461 if (backlight_fading_type & FADING_DOWN) 462 { 463 backlight_fading_state = FADING_DOWN; 464 } 465 else 466 { 467 backlight_fading_state = NOT_FADING; 468 _backlight_fade_update_state(MIN_BRIGHTNESS_SETTING-1); 469 backlight_hw_off(); 470#if (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_HW_REG) 471 /* write the lowest brightness level to the hardware so that 472 * fading up is glitch free */ 473 backlight_hw_brightness(MIN_BRIGHTNESS_SETTING); 474#endif 475#ifdef HAVE_LCD_SLEEP 476 backlight_lcd_sleep_countdown(true); 477#endif 478 } 479} 480#endif /* CONFIG_BACKLIGHT_FADING */ 481 482static inline void do_backlight_off(void) 483{ 484 backlight_timer = 0; 485#if BACKLIGHT_FADE_IN_THREAD 486 backlight_setup_fade_down(); 487#else 488 backlight_hw_off(); 489 /* targets that have fading need to start the countdown when done with 490 * fading */ 491#ifdef HAVE_LCD_SLEEP 492 backlight_lcd_sleep_countdown(true); 493#endif 494#endif 495} 496 497/* Update state of backlight according to timeout setting */ 498static void backlight_update_state(void) 499{ 500 501 int timeout = backlight_get_current_timeout(); 502 503 /* Backlight == OFF in the setting? */ 504 if (UNLIKELY(timeout < 0)) 505 { 506 do_backlight_off(); 507#if defined(HAVE_TRANSFLECTIVE_LCD) && defined(HAVE_LCD_SLEEP) 508 /* LCD must be enabled to allow "passive" operation (backlight always off) */ 509 lcd_awake(); 510#endif 511#if (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_SETTING) \ 512 || (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_HW_REG) 513 /* necessary step to issue fading down when the setting is selected */ 514 if (queue_empty(&backlight_queue)) 515 queue_post(&backlight_queue, SYS_TIMEOUT, 0); 516#endif 517 } 518 else 519 { 520 backlight_timer = timeout; 521 522#ifdef HAVE_LCD_SLEEP 523 backlight_lcd_sleep_countdown(false); /* wake up lcd */ 524#endif 525 526#if BACKLIGHT_FADE_IN_THREAD 527 backlight_setup_fade_up(); 528#else 529 backlight_hw_on(); 530#endif 531 } 532} 533 534#ifdef HAVE_REMOTE_LCD 535/* Update state of remote backlight according to timeout setting */ 536static void remote_backlight_update_state(void) 537{ 538 int timeout = remote_backlight_get_current_timeout(); 539 /* Backlight == OFF in the setting? */ 540 if (timeout < 0) 541 { 542 remote_backlight_timer = 0; /* Disable the timeout */ 543 remote_backlight_hw_off(); 544 } 545 else 546 { 547 remote_backlight_timer = timeout; 548 remote_backlight_hw_on(); 549 } 550} 551#endif /* HAVE_REMOTE_LCD */ 552 553static void backlight_queue_wait(struct queue_event *ev) 554{ 555#if (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_SETTING) \ 556 || (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_HW_REG) 557 if (backlight_fading_state != NOT_FADING) 558 queue_wait_w_tmo(&backlight_queue, ev, FADE_DELAY); 559 else 560#endif 561 queue_wait_w_tmo(&backlight_queue, ev, BACKLIGHT_THREAD_TIMEOUT); 562} 563 564void backlight_thread(void) 565{ 566 struct queue_event ev; 567 bool locked = false; 568 569 while(1) 570 { 571 backlight_queue_wait(&ev); 572 switch(ev.id) 573 { /* These events must always be processed */ 574#ifdef _BACKLIGHT_FADE_BOOST 575 case BACKLIGHT_FADE_FINISH: 576 cpu_boost(false); 577 break; 578#endif 579#ifdef _BACKLIGHT_FADE_ENABLE 580 case BACKLIGHT_FADE_FINISH: 581 _backlight_hw_enable((bl_dim_current|bl_dim_target) != 0); 582 break; 583#endif 584 585#ifndef SIMULATOR 586 /* Here for now or else the aggressive init messes up scrolling */ 587#ifdef HAVE_REMOTE_LCD 588 case SYS_REMOTE_PLUGGED: 589 lcd_remote_on(); 590 lcd_remote_update(); 591 break; 592 593 case SYS_REMOTE_UNPLUGGED: 594 lcd_remote_off(); 595 break; 596#elif defined HAVE_REMOTE_LCD_AS_MAIN 597 case SYS_REMOTE_PLUGGED: 598 lcd_on(); 599 lcd_update(); 600 break; 601 602 case SYS_REMOTE_UNPLUGGED: 603 lcd_off(); 604 break; 605#endif /* HAVE_REMOTE_LCD/ HAVE_REMOTE_LCD_AS_MAIN */ 606#endif /* !SIMULATOR */ 607 case SYS_USB_CONNECTED: 608 usb_acknowledge(SYS_USB_CONNECTED_ACK); 609 break; 610 611#ifdef BACKLIGHT_DRIVER_CLOSE 612 /* Get out of here */ 613 case BACKLIGHT_QUIT: 614 return; 615#endif 616 } 617 if (locked) 618 continue; 619 620 switch(ev.id) 621 { /* These events are only processed if backlight isn't locked */ 622#ifdef HAVE_REMOTE_LCD 623 case REMOTE_BACKLIGHT_TMO_CHANGED: 624 case REMOTE_BACKLIGHT_ON: 625 remote_backlight_update_state(); 626 break; 627 628 case REMOTE_BACKLIGHT_OFF: 629 remote_backlight_timer = 0; /* Disable the timeout */ 630 remote_backlight_hw_off(); 631 break; 632#endif /* HAVE_REMOTE_LCD */ 633 634 case BACKLIGHT_TMO_CHANGED: 635 case BACKLIGHT_ON: 636 backlight_update_state(); 637 break; 638 639 case BACKLIGHT_OFF: 640 do_backlight_off(); 641 break; 642#ifdef HAVE_BACKLIGHT_BRIGHTNESS 643 case BACKLIGHT_BRIGHTNESS_CHANGED: 644 backlight_brightness = (int)ev.data; 645 backlight_hw_brightness((int)ev.data); 646#if (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_SETTING) \ 647 || (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_HW_REG) 648 /* receive backlight brightness */ 649 _backlight_fade_update_state((int)ev.data); 650#endif 651 break; 652#endif /* HAVE_BACKLIGHT_BRIGHTNESS */ 653#ifdef HAVE_LCD_SLEEP 654 case LCD_SLEEP: 655 lcd_sleep(); 656 break; 657#endif 658#ifdef HAVE_BUTTON_LIGHT 659 case BUTTON_LIGHT_TMO_CHANGED: 660 case BUTTON_LIGHT_ON: 661 buttonlight_update_state(); 662 break; 663 664 case BUTTON_LIGHT_OFF: 665 buttonlight_timer = 0; 666 buttonlight_hw_off(); 667 break; 668#ifdef HAVE_BUTTONLIGHT_BRIGHTNESS 669 case BUTTON_LIGHT_BRIGHTNESS_CHANGED: 670 buttonlight_hw_brightness((int)ev.data); 671 break; 672#endif /* HAVE_BUTTONLIGHT_BRIGHTNESS */ 673#endif /* HAVE_BUTTON_LIGHT */ 674 675 case SYS_REBOOT: 676 case SYS_POWEROFF: /* Lock backlight on poweroff so it doesn't */ 677 locked = true; /* go off before power is actually cut. */ 678#if !defined(BOOTLOADER) 679#if defined(HAVE_LCD_SLEEP) /* bugfix ipod Video, 6G crashes if screen off at shutdown */ 680 lcd_awake(); 681#endif 682 if (!global_settings.show_shutdown_message) 683 break; 684#endif 685 /* else fall through */ 686#if CONFIG_CHARGING 687 case SYS_CHARGER_CONNECTED: 688 case SYS_CHARGER_DISCONNECTED: 689#endif 690 backlight_update_state(); 691#ifdef HAVE_REMOTE_LCD 692 remote_backlight_update_state(); 693#endif 694 break; 695 case SYS_TIMEOUT: 696 backlight_handle_timeout(); 697 break; 698 } 699 } /* end while */ 700} 701 702static void backlight_timeout_handler(void) 703{ 704 if(backlight_timer > 0) 705 { 706 backlight_timer -= BACKLIGHT_THREAD_TIMEOUT; 707 if(backlight_timer <= 0) 708 { 709 do_backlight_off(); 710 } 711 } 712#ifdef HAVE_LCD_SLEEP 713 else if(lcd_sleep_timer > 0) 714 { 715 lcd_sleep_timer -= BACKLIGHT_THREAD_TIMEOUT; 716 if(lcd_sleep_timer <= 0) 717 { 718 lcd_sleep(); 719 } 720 } 721#endif /* HAVE_LCD_SLEEP */ 722#ifdef HAVE_REMOTE_LCD 723 if(remote_backlight_timer > 0) 724 { 725 remote_backlight_timer -= BACKLIGHT_THREAD_TIMEOUT; 726 if(remote_backlight_timer <= 0) 727 { 728 remote_backlight_hw_off(); 729 } 730 } 731#endif /* HAVE_REMOVE_LCD */ 732#ifdef HAVE_BUTTON_LIGHT 733 if (buttonlight_timer > 0) 734 { 735 buttonlight_timer -= BACKLIGHT_THREAD_TIMEOUT; 736 if (buttonlight_timer <= 0) 737 { 738 buttonlight_hw_off(); 739 } 740 } 741 if (buttonlight_ignored_timer > 0) 742 { 743 buttonlight_ignored_timer -= BACKLIGHT_THREAD_TIMEOUT; 744 if (buttonlight_ignored_timer <= 0) 745 ignore_buttonlight_on = false; 746 } 747#endif /* HAVE_BUTTON_LIGHT */ 748 if (backlight_ignored_timer > 0) 749 { 750 backlight_ignored_timer -= BACKLIGHT_THREAD_TIMEOUT; 751 if (backlight_ignored_timer <= 0) 752 ignore_backlight_on = false; 753 } 754} 755 756static void backlight_handle_timeout(void) 757{ 758#if (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_SETTING) \ 759 || (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_SW_HW_REG) 760 if (backlight_fading_state != NOT_FADING) 761 { 762 if ((_backlight_fade_step(backlight_fading_state))) 763 { /* finished fading */ 764#ifdef HAVE_LCD_SLEEP 765 if (backlight_fading_state == FADING_DOWN) 766 { /* start sleep countdown */ 767 backlight_lcd_sleep_countdown(true); 768 } 769#endif 770 backlight_fading_state = NOT_FADING; 771 } 772 } 773 else 774#endif /* CONFIG_BACKLIGHT_FADING */ 775 backlight_timeout_handler(); 776} 777 778void backlight_init(void) 779{ 780 queue_init(&backlight_queue, true); 781 782 if (backlight_hw_init()) 783 { 784#if (CONFIG_BACKLIGHT_FADING == BACKLIGHT_FADING_PWM) 785 /* If backlight is already on, don't fade in. */ 786 bl_dim_target = BL_PWM_COUNT; 787 bl_dim_fraction = (BL_PWM_COUNT<<16); 788#endif 789 } 790 /* Leave all lights as set by the bootloader here. The settings load will 791 * call the appropriate backlight_set_*() functions, only changing light 792 * status if necessary. */ 793#ifdef BACKLIGHT_DRIVER_CLOSE 794 backlight_thread_id = 795#endif 796 create_thread(backlight_thread, backlight_stack, 797 sizeof(backlight_stack), 0, backlight_thread_name 798 IF_PRIO(, PRIORITY_USER_INTERFACE) 799 IF_COP(, CPU)); 800} 801 802#ifdef BACKLIGHT_DRIVER_CLOSE 803void backlight_close(void) 804{ 805 unsigned int thread = backlight_thread_id; 806 807 /* Wait for thread to exit */ 808 if (thread == 0) 809 return; 810 811 backlight_thread_id = 0; 812 813 queue_post(&backlight_queue, BACKLIGHT_QUIT, 0); 814 thread_wait(thread); 815} 816#endif /* BACKLIGHT_DRIVER_CLOSE */ 817 818void backlight_on(void) 819{ 820 if(!ignore_backlight_on) 821 { 822 queue_remove_from_head(&backlight_queue, BACKLIGHT_ON); 823 queue_post(&backlight_queue, BACKLIGHT_ON, 0); 824 } 825} 826 827void backlight_on_ignore(bool value, int timeout) 828{ 829 ignore_backlight_on = value; 830 backlight_ignored_timer = timeout; 831} 832 833void backlight_off(void) 834{ 835 queue_post(&backlight_queue, BACKLIGHT_OFF, 0); 836} 837 838/* returns true when the backlight is on, 839 * and optionally when it's set to always off. */ 840bool is_backlight_on(bool ignore_always_off) 841{ 842 int timeout = backlight_get_current_timeout(); 843 return (backlight_timer > 0) /* countdown */ 844 || (timeout == 0) /* always on */ 845 || ((timeout < 0) && !ignore_always_off); 846} 847 848/* return value in ticks; 0 means always on, <0 means always off */ 849int backlight_get_current_timeout(void) 850{ 851 if ((backlight_on_button_hold != 0) 852#if (defined(HAVE_REMOTE_LCD_AS_MAIN) && defined(HAS_REMOTE_BUTTON_HOLD)) 853 && remote_button_hold() 854#elif defined(HAS_BUTTON_HOLD) 855 && button_hold() 856#else 857 && is_keys_locked() 858#endif 859 ) 860 return (backlight_on_button_hold == 2) ? 0 : -1; 861 /* always on or always off */ 862 else 863#if CONFIG_CHARGING 864 if (power_input_present()) 865 return backlight_timeout_plugged; 866 else 867#endif 868 return backlight_timeout_normal; 869} 870 871void backlight_set_timeout(int value) 872{ 873 backlight_timeout_normal = HZ * value; 874 queue_post(&backlight_queue, BACKLIGHT_TMO_CHANGED, 0); 875} 876 877#if CONFIG_CHARGING 878void backlight_set_timeout_plugged(int value) 879{ 880 backlight_timeout_plugged = HZ * value; 881 queue_post(&backlight_queue, BACKLIGHT_TMO_CHANGED, 0); 882} 883#endif /* CONFIG_CHARGING */ 884 885#ifdef HAS_BUTTON_HOLD 886/* Hold button change event handler. */ 887void backlight_hold_changed(bool hold_button) 888{ 889 if (!hold_button || (backlight_on_button_hold > 0)) 890 { 891 /* if unlocked or override in effect */ 892 893 /*backlight_on(); REMOVED*/ 894 queue_remove_from_head(&backlight_queue, BACKLIGHT_ON); 895 queue_post(&backlight_queue, BACKLIGHT_ON, 0); 896 } 897} 898#endif /* HAS_BUTTON_HOLD */ 899 900void backlight_set_on_button_hold(int index) 901{ 902 if ((unsigned)index >= 3) 903 /* if given a weird value, use default */ 904 index = 0; 905 906 backlight_on_button_hold = index; 907 queue_post(&backlight_queue, BACKLIGHT_TMO_CHANGED, 0); 908} 909 910#ifdef HAVE_LCD_SLEEP_SETTING 911void lcd_set_sleep_after_backlight_off(int timeout_seconds) 912{ 913 lcd_sleep_timeout = HZ * timeout_seconds; 914 915 if (is_backlight_on(true)) 916 /* Timer will be set when bl turns off or bl set to on. */ 917 return; 918 919 /* Backlight is Off */ 920 if (lcd_sleep_timeout < 0) 921 lcd_sleep_timer = 0; /* Never */ 922 else if (lcd_sleep_timeout == 0) 923 lcd_sleep_timer = 1; /* Always - sleep next tick */ 924 else 925 lcd_sleep_timer = lcd_sleep_timeout; /* other */ 926} 927#endif /* HAVE_LCD_SLEEP_SETTING */ 928 929#ifdef HAVE_REMOTE_LCD 930void remote_backlight_on(void) 931{ 932 queue_post(&backlight_queue, REMOTE_BACKLIGHT_ON, 0); 933} 934 935void remote_backlight_off(void) 936{ 937 queue_post(&backlight_queue, REMOTE_BACKLIGHT_OFF, 0); 938} 939 940void remote_backlight_set_timeout(int value) 941{ 942 remote_backlight_timeout_normal = HZ * value; 943 queue_post(&backlight_queue, REMOTE_BACKLIGHT_TMO_CHANGED, 0); 944} 945 946#if CONFIG_CHARGING 947void remote_backlight_set_timeout_plugged(int value) 948{ 949 remote_backlight_timeout_plugged = HZ * value; 950 queue_post(&backlight_queue, REMOTE_BACKLIGHT_TMO_CHANGED, 0); 951} 952#endif /* CONFIG_CHARGING */ 953 954#ifdef HAS_REMOTE_BUTTON_HOLD 955/* Remote hold button change event handler. */ 956void remote_backlight_hold_changed(bool rc_hold_button) 957{ 958 if (!rc_hold_button || (remote_backlight_on_button_hold > 0)) 959 /* if unlocked or override */ 960 remote_backlight_on(); 961} 962 963void remote_backlight_set_on_button_hold(int index) 964{ 965 if ((unsigned)index >= 3) 966 /* if given a weird value, use default */ 967 index = 0; 968 969 remote_backlight_on_button_hold = index; 970 queue_post(&backlight_queue, REMOTE_BACKLIGHT_TMO_CHANGED, 0); 971} 972#endif /* HAS_REMOTE_BUTTON_HOLD */ 973 974/* return value in ticks; 0 means always on, <0 means always off */ 975int remote_backlight_get_current_timeout(void) 976{ 977#ifdef HAS_REMOTE_BUTTON_HOLD 978 if (remote_button_hold() && (remote_backlight_on_button_hold != 0)) 979 return (remote_backlight_on_button_hold == 2) 980 ? 0 : -1; /* always on or always off */ 981 else 982#endif 983#if CONFIG_CHARGING 984 if (power_input_present()) 985 return remote_backlight_timeout_plugged; 986 else 987#endif 988 return remote_backlight_timeout_normal; 989} 990 991/* returns true when the backlight is on, and 992 * optionally when it's set to always off */ 993bool is_remote_backlight_on(bool ignore_always_off) 994{ 995 int timeout = remote_backlight_get_current_timeout(); 996 return (remote_backlight_timer > 0) /* countdown */ 997 || (timeout == 0) /* always on */ 998 || ((timeout < 0) && !ignore_always_off); 999} 1000 1001#endif /* HAVE_REMOTE_LCD */ 1002 1003#ifdef HAVE_BACKLIGHT_BRIGHTNESS 1004void backlight_set_brightness(int val) 1005{ 1006 if (val < MIN_BRIGHTNESS_SETTING) 1007 val = MIN_BRIGHTNESS_SETTING; 1008 else if (val > MAX_BRIGHTNESS_SETTING) 1009 val = MAX_BRIGHTNESS_SETTING; 1010 1011 queue_post(&backlight_queue, BACKLIGHT_BRIGHTNESS_CHANGED, val); 1012} 1013#endif /* HAVE_BACKLIGHT_BRIGHTNESS */ 1014 1015#ifdef HAVE_BUTTONLIGHT_BRIGHTNESS 1016void buttonlight_set_brightness(int val) 1017{ 1018 if (val < MIN_BRIGHTNESS_SETTING) 1019 val = MIN_BRIGHTNESS_SETTING; 1020 else if (val > MAX_BRIGHTNESS_SETTING) 1021 val = MAX_BRIGHTNESS_SETTING; 1022 1023 queue_post(&backlight_queue, BUTTON_LIGHT_BRIGHTNESS_CHANGED, val); 1024} 1025#endif /* HAVE_BUTTONLIGHT_BRIGHTNESS */ 1026 1027#else /* !defined(HAVE_BACKLIGHT) || !defined(BACKLIGHT_FULL_INIT) 1028 -- no backlight, empty dummy functions */ 1029 1030#if defined(HAVE_BACKLIGHT) && !defined(BACKLIGHT_FULL_INIT) 1031void backlight_init(void) 1032{ 1033 (void)backlight_hw_init(); 1034 backlight_hw_on(); 1035} 1036#endif 1037 1038void backlight_on(void) {} 1039void backlight_off(void) {} 1040void backlight_set_timeout(int value) {(void)value;} 1041 1042bool is_backlight_on(bool ignore_always_off) 1043{ 1044 (void)ignore_always_off; 1045 return true; 1046} 1047#ifdef HAVE_REMOTE_LCD 1048void remote_backlight_on(void) {} 1049void remote_backlight_off(void) {} 1050void remote_backlight_set_timeout(int value) {(void)value;} 1051 1052bool is_remote_backlight_on(bool ignore_always_off) 1053{ 1054 (void)ignore_always_off; 1055 return true; 1056} 1057#endif /* HAVE_REMOTE_LCD */ 1058#ifdef HAVE_BACKLIGHT_BRIGHTNESS 1059void backlight_set_brightness(int val) { (void)val; } 1060#endif 1061 1062#ifdef HAVE_BUTTON_LIGHT 1063void buttonlight_on(void) {} 1064#ifdef HAVE_BUTTONLIGHT_BRIGHTNESS 1065void buttonlight_set_brightness(int val) { (void)val; } 1066#endif 1067#endif /* HAVE_BUTTON_LIGHT */ 1068 1069#endif /* defined(HAVE_BACKLIGHT) && defined(BACKLIGHT_FULL_INIT) */ 1070 1071#ifndef HAVE_BUTTON_LIGHT /* Dummy Functions */ 1072void buttonlight_on(void) {} 1073void buttonlight_on_ignore(bool value, int timeout){(void)value;(void)timeout;} 1074void buttonlight_off(void) {} 1075void buttonlight_set_timeout(int value) {(void)value;} 1076#endif /* ndef HAVE_BUTTON_LIGHT */ 1077 1078#ifndef HAVE_BUTTONLIGHT_BRIGHTNESS /* Dummy Functions */ 1079void buttonlight_set_brightness(int val) { (void)val; } 1080#endif /* ndef HAVE_BUTTONLIGHT_BRIGHTNESS */