summaryrefslogtreecommitdiff
path: root/firmware/target/arm/s3c2440/gigabeat-fx/backlight-meg-fx.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/s3c2440/gigabeat-fx/backlight-meg-fx.c')
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/backlight-meg-fx.c692
1 files changed, 692 insertions, 0 deletions
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/backlight-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/backlight-meg-fx.c
new file mode 100644
index 0000000000..a1b6a8a583
--- /dev/null
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/backlight-meg-fx.c
@@ -0,0 +1,692 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Linus Nielsen Feltzing
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "config.h"
20#include "cpu.h"
21#include "system.h"
22#include "backlight-target.h"
23#include "backlight.h"
24#include "lcd.h"
25#include "sc606-meg-fx.h"
26#include "power.h"
27
28
29#define FLICKER_PERIOD 15
30#define BUTTONLIGHT_MENU (SC606_LED_B1)
31#define BUTTONLIGHT_ALL (SC606_LED_B1 | SC606_LED_B2 | SC606_LED_C1 | SC606_LED_C2)
32
33static void led_control_service(void);
34static unsigned short backlight_brightness;
35static unsigned short backlight_current;
36static unsigned short backlight_target;
37static unsigned short time_til_fade;
38static unsigned short fade_interval;
39static unsigned short initial_tick_delay;
40static unsigned char backlight_leds;
41
42static enum backlight_states
43{
44 BACKLIGHT_CONTROL_IDLE,
45 BACKLIGHT_CONTROL_OFF,
46 BACKLIGHT_CONTROL_ON,
47 BACKLIGHT_CONTROL_SET,
48 BACKLIGHT_CONTROL_FADE_OFF,
49 BACKLIGHT_CONTROL_FADE_ON,
50 BACKLIGHT_CONTROL_FADE_ON_FROM_OFF
51} backlight_control;
52
53
54
55enum buttonlight_states
56{
57 /* turn button lights off */
58 BUTTONLIGHT_MODE_OFF_ENTRY,
59 BUTTONLIGHT_MODE_OFF,
60
61 /* turns button lights on to setting */
62 BUTTONLIGHT_MODE_ON_ENTRY,
63 BUTTONLIGHT_MODE_ON,
64
65 /* turns button lights on to minimum */
66 BUTTONLIGHT_MODE_FAINT_ENTRY,
67 BUTTONLIGHT_MODE_FAINT,
68
69 /* allows button lights to flicker when triggered */
70 BUTTONLIGHT_MODE_FLICKER_ENTRY,
71 BUTTONLIGHT_MODE_FLICKER,
72 BUTTONLIGHT_MODE_FLICKERING,
73
74 /* button lights solid */
75 BUTTONLIGHT_MODE_SOLID_ENTRY,
76 BUTTONLIGHT_MODE_SOLID,
77
78 /* button light charing */
79 BUTTONLIGHT_MODE_CHARGING_ENTRY,
80 BUTTONLIGHT_MODE_CHARGING,
81 BUTTONLIGHT_MODE_CHARGING_WAIT,
82
83 /* internal use only */
84 BUTTONLIGHT_HELPER_SET,
85 BUTTONLIGHT_HELPER_SET_FINAL,
86 BUTTONLIGHT_MODE_STOP,
87
88 /* buttonlights follow the backlight settings */
89 BUTTONLIGHT_MODE_FOLLOW_ENTRY,
90 BUTTONLIGHT_MODE_FOLLOW,
91};
92
93
94
95static char buttonlight_leds;
96static unsigned short buttonlight_setting;
97static unsigned short buttonlight_current;
98static unsigned char buttonlight_selected;
99static enum buttonlight_states buttonlight_state;
100static enum buttonlight_states buttonlight_saved_state;
101static unsigned short buttonlight_flickering;
102
103static unsigned short buttonlight_trigger_now;
104static unsigned short buttonlight_trigger_brightness;
105
106
107
108static unsigned short charging_led_index;
109static unsigned short buttonlight_charging_counter;
110
111#define CHARGING_LED_COUNT 60
112unsigned char charging_leds[] = { 0x00, 0x20, 0x38, 0x3C };
113
114
115
116bool __backlight_init(void)
117{
118 backlight_control = BACKLIGHT_CONTROL_IDLE;
119
120 backlight_current = DEFAULT_BRIGHTNESS_SETTING;
121
122 buttonlight_state = BUTTONLIGHT_MODE_OFF;
123
124 buttonlight_selected = 0x04;
125
126 /* delay 4 seconds before any fading */
127 initial_tick_delay = 400;
128 /* put the led control on the tick list */
129 tick_add_task(led_control_service);
130
131 return true;
132}
133
134
135
136void __backlight_on(void)
137{
138 /* now go turn the backlight on */
139 backlight_control = BACKLIGHT_CONTROL_ON;
140}
141
142
143
144void __backlight_off(void)
145{
146 backlight_control = BACKLIGHT_CONTROL_OFF;
147}
148
149
150
151/* Assumes that the backlight has been initialized */
152void __backlight_set_brightness(int brightness)
153{
154 /* stop the interrupt from messing us up */
155 backlight_control = BACKLIGHT_CONTROL_IDLE;
156
157 backlight_brightness = brightness + 1;
158
159 /* only set the brightness if it is different from the current */
160 if (backlight_brightness != backlight_current)
161 {
162 backlight_control = BACKLIGHT_CONTROL_SET;
163 }
164}
165
166
167
168/* only works if the buttonlight mode is set to triggered mode */
169void __buttonlight_trigger(void)
170{
171 buttonlight_trigger_now = 1;
172}
173
174
175
176
177/* map the mode from the command into the state machine entries */
178void __buttonlight_mode(enum buttonlight_mode mode,
179 enum buttonlight_selection selection,
180 unsigned short brightness)
181{
182 /* choose stop to setup mode */
183 buttonlight_state = BUTTONLIGHT_MODE_STOP;
184
185
186 /* clip brightness */
187 if (brightness > MAX_BRIGHTNESS_SETTING)
188 {
189 brightness = MAX_BRIGHTNESS_SETTING;
190 }
191
192 brightness++;
193
194 /* Select which LEDs to use */
195 switch (selection)
196 {
197 case BUTTONLIGHT_LED_ALL:
198 buttonlight_selected = BUTTONLIGHT_ALL;
199 break;
200
201 case BUTTONLIGHT_LED_MENU:
202 buttonlight_selected = BUTTONLIGHT_MENU;
203 break;
204 }
205
206 /* which mode to use */
207 switch (mode)
208 {
209 case BUTTONLIGHT_OFF:
210 buttonlight_state = BUTTONLIGHT_MODE_OFF_ENTRY;
211 break;
212
213 case BUTTONLIGHT_ON:
214 buttonlight_trigger_brightness = brightness;
215 buttonlight_state = BUTTONLIGHT_MODE_ON_ENTRY;
216 break;
217
218 /* faint is just a quick way to set ON to 1 */
219 case BUTTONLIGHT_FAINT:
220 buttonlight_trigger_brightness = 1;
221 buttonlight_state = BUTTONLIGHT_MODE_ON_ENTRY;
222 break;
223
224 case BUTTONLIGHT_FLICKER:
225 buttonlight_trigger_brightness = brightness;
226 buttonlight_state = BUTTONLIGHT_MODE_FLICKER_ENTRY;
227 break;
228
229 case BUTTONLIGHT_SIGNAL:
230 buttonlight_trigger_brightness = brightness;
231 buttonlight_state = BUTTONLIGHT_MODE_SOLID_ENTRY;
232 break;
233
234 case BUTTONLIGHT_FOLLOW:
235 buttonlight_state = BUTTONLIGHT_MODE_FOLLOW_ENTRY;
236 break;
237
238 case BUTTONLIGHT_CHARGING:
239 buttonlight_state = BUTTONLIGHT_MODE_CHARGING_ENTRY;
240 break;
241
242 default:
243 return; /* unknown mode */
244 }
245
246
247}
248
249
250
251/*
252 * The button lights have 'modes' of operation. Each mode must setup and
253 * execute its own operation - taking care that this is all done in an ISR.
254 *
255 */
256
257
258
259/* led_control_service runs in interrupt context - be brief!
260 * This service is called once per interrupt timer tick - 100 times a second.
261 *
262 * There should be at most only one i2c operation per call - if more are need
263 * the calls should be spread across calls.
264 *
265 * Putting all led servicing in one thread means that we wont step on any
266 * i2c operations - they are all serialized here in the ISR tick. It also
267 * insures that we get called at equal timing for good visual effect.
268 *
269 * The buttonlight service runs only after all backlight services have finished.
270 * Fading the buttonlights is possible, but not recommended because of the
271 * additional calls needed during the ISR
272 */
273static void led_control_service(void)
274{
275 if(initial_tick_delay) {
276 initial_tick_delay--;
277 return;
278 }
279 switch (backlight_control)
280 {
281 case BACKLIGHT_CONTROL_IDLE:
282 switch (buttonlight_state)
283 {
284 case BUTTONLIGHT_MODE_STOP: break;
285
286 /* Buttonlight mode: OFF */
287 case BUTTONLIGHT_MODE_OFF_ENTRY:
288 if (buttonlight_current)
289 {
290 buttonlight_leds = 0x00;
291 sc606_write(SC606_REG_CONF, backlight_leds);
292 buttonlight_current = 0;
293 }
294 buttonlight_state = BUTTONLIGHT_MODE_OFF;
295 break;
296
297 case BUTTONLIGHT_MODE_OFF:
298 break;
299
300
301 /* button mode: CHARGING - show charging sequence */
302 case BUTTONLIGHT_MODE_CHARGING_ENTRY:
303 /* start turned off */
304 buttonlight_leds = 0x00;
305 sc606_write(SC606_REG_CONF, backlight_leds);
306 buttonlight_current = 0;
307
308 /* temporary save for the next mode - then to do settings */
309 buttonlight_setting = DEFAULT_BRIGHTNESS_SETTING;
310 buttonlight_saved_state = BUTTONLIGHT_MODE_CHARGING_WAIT;
311 buttonlight_state = BUTTONLIGHT_HELPER_SET;
312 break;
313
314
315 case BUTTONLIGHT_MODE_CHARGING:
316 if (--buttonlight_charging_counter == 0)
317 {
318 /* change led */
319 if (charging_state())
320 {
321 buttonlight_leds = charging_leds[charging_led_index];
322 if (++charging_led_index >= sizeof(charging_leds))
323 {
324 charging_led_index = 0;
325 }
326 sc606_write(SC606_REG_CONF, backlight_leds | buttonlight_leds);
327 buttonlight_charging_counter = CHARGING_LED_COUNT;
328 }
329 else
330 {
331 buttonlight_state = BUTTONLIGHT_MODE_CHARGING_ENTRY;
332 }
333 }
334 break;
335
336 /* wait for the charget to be plugged in */
337 case BUTTONLIGHT_MODE_CHARGING_WAIT:
338 if (charging_state())
339 {
340 charging_led_index = 0;
341 buttonlight_charging_counter = CHARGING_LED_COUNT;
342 buttonlight_state = BUTTONLIGHT_MODE_CHARGING;
343 }
344 break;
345
346
347 /* Buttonlight mode: FOLLOW - try to stay current with backlight
348 * since this runs in the idle of the backlight it will not really
349 * follow in real time
350 */
351 case BUTTONLIGHT_MODE_FOLLOW_ENTRY:
352 /* case 1 - backlight on, but buttonlight is off */
353 if (backlight_current)
354 {
355 /* Turn the buttonlights on */
356 buttonlight_leds = buttonlight_selected;
357 sc606_write(SC606_REG_CONF, backlight_leds | buttonlight_leds);
358
359 /* temporary save for the next mode - then to do settings */
360 buttonlight_setting = backlight_current;
361 buttonlight_saved_state = BUTTONLIGHT_MODE_FOLLOW;
362 buttonlight_state = BUTTONLIGHT_HELPER_SET;
363 }
364 /* case 2 - backlight off, but buttonlight is on */
365 else
366 {
367 buttonlight_current = 0;
368 buttonlight_leds = 0x00;
369 sc606_write(SC606_REG_CONF, backlight_leds);
370 buttonlight_state = BUTTONLIGHT_MODE_FOLLOW;
371 }
372 break;
373
374 case BUTTONLIGHT_MODE_FOLLOW:
375 if (buttonlight_current != backlight_current)
376 {
377 /* case 1 - backlight on, but buttonlight is off */
378 if (backlight_current)
379 {
380 if (0 == buttonlight_current)
381 {
382 /* Turn the buttonlights on */
383 buttonlight_leds = buttonlight_selected;
384 sc606_write(SC606_REG_CONF, backlight_leds | buttonlight_leds);
385 }
386
387 /* temporary save for the next mode - then to do settings */
388 buttonlight_setting = backlight_current;
389 buttonlight_saved_state = BUTTONLIGHT_MODE_FOLLOW;
390 buttonlight_state = BUTTONLIGHT_HELPER_SET;
391 }
392
393 /* case 2 - backlight off, but buttonlight is on */
394 else
395 {
396 buttonlight_current = 0;
397 buttonlight_leds = 0x00;
398 sc606_write(SC606_REG_CONF, backlight_leds);
399 }
400
401 }
402 break;
403
404
405
406 /* Buttonlight mode: ON - stays at the set brightness */
407 case BUTTONLIGHT_MODE_ON_ENTRY:
408 buttonlight_leds = buttonlight_selected;
409 sc606_write(SC606_REG_CONF, backlight_leds | buttonlight_leds);
410
411 /* temporary save for the next mode - then to do settings */
412 buttonlight_setting = buttonlight_trigger_brightness;
413 buttonlight_saved_state = BUTTONLIGHT_MODE_ON;
414 buttonlight_state = BUTTONLIGHT_HELPER_SET;
415 break;
416
417 case BUTTONLIGHT_MODE_ON:
418 break;
419
420
421
422 /* Buttonlight mode: FLICKER */
423 case BUTTONLIGHT_MODE_FLICKER_ENTRY:
424 /* already on? turn it off */
425 if (buttonlight_current)
426 {
427 buttonlight_leds = 0x00;
428 sc606_write(SC606_REG_CONF, backlight_leds);
429 buttonlight_current = 0;
430 }
431
432 /* set the brightness if not already set */
433 if (buttonlight_current != buttonlight_trigger_brightness)
434 {
435 /* temporary save for the next mode - then to do settings */
436 buttonlight_setting = buttonlight_trigger_brightness;
437 buttonlight_saved_state = BUTTONLIGHT_MODE_FLICKER;
438 buttonlight_state = BUTTONLIGHT_HELPER_SET;
439 }
440 else buttonlight_state = BUTTONLIGHT_MODE_FLICKER;
441 break;
442
443
444 case BUTTONLIGHT_MODE_FLICKER:
445 /* wait for the foreground to trigger flickering */
446 if (buttonlight_trigger_now)
447 {
448 /* turn them on */
449 buttonlight_leds = buttonlight_selected;
450 buttonlight_current = buttonlight_setting;
451 sc606_write(SC606_REG_CONF, backlight_leds | buttonlight_leds);
452
453 /* reset the trigger and go flicker the LEDs */
454 buttonlight_trigger_now = 0;
455 buttonlight_flickering = FLICKER_PERIOD;
456 buttonlight_state = BUTTONLIGHT_MODE_FLICKERING;
457 }
458 break;
459
460
461 case BUTTONLIGHT_MODE_FLICKERING:
462 /* flicker the LEDs for as long as we get triggered */
463 if (buttonlight_flickering)
464 {
465 /* turn the leds off if they are on */
466 if (buttonlight_current)
467 {
468 buttonlight_leds = 0x00;
469 sc606_write(SC606_REG_CONF, backlight_leds);
470 buttonlight_current = 0;
471 }
472
473 buttonlight_flickering--;
474 }
475 else
476 {
477 /* is flickering triggered again? */
478 if (!buttonlight_trigger_now)
479 {
480 /* completed a cycle - no new triggers - go back and wait */
481 buttonlight_state = BUTTONLIGHT_MODE_FLICKER;
482 }
483 else
484 {
485 /* reset flickering */
486 buttonlight_trigger_now = 0;
487 buttonlight_flickering = FLICKER_PERIOD;
488
489 /* turn buttonlights on */
490 buttonlight_leds = buttonlight_selected;
491 buttonlight_current = buttonlight_setting;
492 sc606_write(SC606_REG_CONF, backlight_leds | buttonlight_leds);
493 }
494 }
495 break;
496
497
498 /* Buttonlight mode: SIGNAL / SOLID */
499 case BUTTONLIGHT_MODE_SOLID_ENTRY:
500 /* already on? turn it off */
501 if (buttonlight_current)
502 {
503 buttonlight_leds = 0x00;
504 sc606_write(SC606_REG_CONF, backlight_leds);
505 buttonlight_current = 0;
506 }
507
508 /* set the brightness if not already set */
509 /* temporary save for the next mode - then to do settings */
510 buttonlight_setting = buttonlight_trigger_brightness;
511 buttonlight_saved_state = BUTTONLIGHT_MODE_SOLID;
512 buttonlight_state = BUTTONLIGHT_HELPER_SET;
513 break;
514
515
516 case BUTTONLIGHT_MODE_SOLID:
517 /* wait for the foreground to trigger */
518 if (buttonlight_trigger_now)
519 {
520 /* turn them on if not already on */
521 if (0 == buttonlight_current)
522 {
523 buttonlight_leds = buttonlight_selected;
524 buttonlight_current = buttonlight_setting;
525 sc606_write(SC606_REG_CONF, backlight_leds | buttonlight_leds);
526 }
527
528 /* reset the trigger */
529 buttonlight_trigger_now = 0;
530 }
531 else
532 {
533 if (buttonlight_current)
534 {
535 buttonlight_leds = 0x00;
536 sc606_write(SC606_REG_CONF, backlight_leds);
537 buttonlight_current = 0;
538 }
539 }
540 break;
541
542
543 /* set the brightness for the buttonlights - takes 2 passes */
544 case BUTTONLIGHT_HELPER_SET:
545 sc606_write(SC606_REG_B, buttonlight_setting-1);
546 buttonlight_state = BUTTONLIGHT_HELPER_SET_FINAL;
547 break;
548
549 case BUTTONLIGHT_HELPER_SET_FINAL:
550 sc606_write(SC606_REG_C, buttonlight_setting-1);
551 buttonlight_current = buttonlight_setting;
552 buttonlight_state = buttonlight_saved_state;
553 break;
554
555 default:
556 break;
557
558 }
559 break;
560
561
562 case BACKLIGHT_CONTROL_FADE_ON_FROM_OFF:
563 backlight_leds = 0x03;
564 sc606_write(SC606_REG_CONF, 0x03 | buttonlight_leds);
565 backlight_control = BACKLIGHT_CONTROL_FADE_ON;
566 break;
567
568
569 case BACKLIGHT_CONTROL_OFF:
570 backlight_current = 0;
571 backlight_leds = 0x00;
572 sc606_write(SC606_REG_CONF, buttonlight_leds);
573 backlight_control = BACKLIGHT_CONTROL_IDLE;
574
575 break;
576
577
578 case BACKLIGHT_CONTROL_ON:
579 backlight_leds = 0x03;
580 sc606_write(SC606_REG_CONF, 0x03 | buttonlight_leds);
581 backlight_current = backlight_brightness;
582 backlight_control = BACKLIGHT_CONTROL_IDLE;
583 break;
584
585
586 case BACKLIGHT_CONTROL_SET:
587 /* The SC606 LED driver can set the brightness in 64 steps */
588 sc606_write(SC606_REG_A, backlight_brightness-1);
589
590 /* if we were turned off - turn the backlight on */
591 if (backlight_current)
592 {
593 backlight_current = backlight_brightness;
594 backlight_control = BACKLIGHT_CONTROL_IDLE;
595 }
596 else
597 {
598 backlight_control = BACKLIGHT_CONTROL_ON;
599 }
600 break;
601
602
603 case BACKLIGHT_CONTROL_FADE_ON:
604 if (--time_til_fade) return;
605
606 /* The SC606 LED driver can set the brightness in 64 steps */
607 sc606_write(SC606_REG_A, backlight_current++);
608
609 /* have we hit the target? */
610 if (backlight_current == backlight_target)
611 {
612 backlight_control = BACKLIGHT_CONTROL_IDLE;
613 }
614 else
615 {
616 time_til_fade = fade_interval;
617 }
618 break;
619
620
621 case BACKLIGHT_CONTROL_FADE_OFF:
622 if (--time_til_fade) return;
623
624 /* The SC606 LED driver can set the brightness in 64 steps */
625 sc606_write(SC606_REG_A, --backlight_current);
626
627 /* have we hit the target? */
628 if (backlight_current == backlight_target)
629 {
630 if (backlight_current)
631 {
632 backlight_control = BACKLIGHT_CONTROL_IDLE;
633 }
634 else
635 {
636 backlight_control = BACKLIGHT_CONTROL_OFF;
637 }
638
639 }
640 else
641 {
642 time_til_fade = fade_interval;
643 }
644 break;
645 }
646
647 if(backlight_current)
648 lcd_enable(true);
649 else
650 lcd_enable(false);
651}
652
653
654
655
656
657void __backlight_dim(bool dim_now)
658{
659 unsigned short target;
660
661 /* dont let the interrupt tick happen */
662 backlight_control = BACKLIGHT_CONTROL_IDLE;
663
664 target = (dim_now == true) ? 0 : backlight_brightness;
665
666 /* only try and fade if the target is different */
667 if (backlight_current != target)
668 {
669 backlight_target = target;
670
671 if (backlight_current > backlight_target)
672 {
673 time_til_fade = fade_interval = 4;
674 backlight_control = BACKLIGHT_CONTROL_FADE_OFF;
675 }
676 else
677 {
678 time_til_fade = fade_interval = 1;
679 if (backlight_current)
680 {
681 backlight_control = BACKLIGHT_CONTROL_FADE_ON;
682 }
683 else
684 {
685 backlight_control = BACKLIGHT_CONTROL_FADE_ON_FROM_OFF;
686 }
687 }
688 }
689
690}
691
692