1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
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.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
31 #include "backlight.h"
33 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
34 #include "pcf50606.h" /* iRiver brightness */
37 #if CONFIG_BACKLIGHT == BL_IRIVER_H300
38 #include "lcd.h" /* for lcd_enable() */
40 #ifdef HAVE_REMOTE_LCD
41 #include "lcd-remote.h"
44 #if defined(CONFIG_BACKLIGHT) && !defined(BOOTLOADER)
46 const char backlight_timeout_value
[19] =
48 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 45, 60, 90
51 #define BACKLIGHT_ON 1
52 #define BACKLIGHT_OFF 2
53 #define REMOTE_BACKLIGHT_ON 3
54 #define REMOTE_BACKLIGHT_OFF 4
55 #define BACKLIGHT_UNBOOST_CPU 5
57 static void backlight_thread(void);
58 static long backlight_stack
[DEFAULT_STACK_SIZE
/sizeof(long)];
59 static const char backlight_thread_name
[] = "backlight";
60 static struct event_queue backlight_queue
;
62 static int backlight_timer
;
63 static int backlight_timeout
= 5*HZ
;
65 static int backlight_timeout_plugged
= 5*HZ
;
68 #ifdef HAVE_REMOTE_LCD
69 static int remote_backlight_timer
;
70 static int remote_backlight_timeout
= 5*HZ
;
72 static int remote_backlight_timeout_plugged
= 5*HZ
;
76 #if (CONFIG_BACKLIGHT == BL_IRIVER_H100) && !defined(SIMULATOR)
77 /* backlight fading */
78 #define BL_PWM_INTERVAL 5000 /* Cycle interval in µs */
79 #define BL_PWM_COUNT 100
80 static const char backlight_fade_value
[8] = { 0, 1, 2, 4, 6, 8, 10, 20 };
81 static int fade_in_count
= 1;
82 static int fade_out_count
= 4;
84 static bool bl_timer_active
= false;
85 static int bl_dim_current
= BL_PWM_COUNT
;
86 static int bl_dim_target
= BL_PWM_COUNT
;
87 static int bl_pwm_counter
= 0;
88 static volatile int bl_cycle_counter
= 0;
89 static enum {DIM_STATE_START
, DIM_STATE_MAIN
} bl_dim_state
= DIM_STATE_START
;
91 static void backlight_isr(void)
96 timer_period
= CPU_FREQ
/ 1000 * BL_PWM_INTERVAL
/ 1000;
100 case DIM_STATE_START
:
104 if (bl_dim_current
> 0 && bl_dim_current
< BL_PWM_COUNT
)
106 and_l(~0x00020000, &GPIO1_OUT
);
107 bl_pwm_counter
= bl_dim_current
;
108 timer_period
= timer_period
* bl_pwm_counter
/ BL_PWM_COUNT
;
109 bl_dim_state
= DIM_STATE_MAIN
;
114 and_l(~0x00020000, &GPIO1_OUT
);
116 or_l(0x00020000, &GPIO1_OUT
);
118 if (bl_dim_current
== bl_dim_target
)
124 /* Dim main screen */
126 or_l(0x00020000, &GPIO1_OUT
);
127 bl_dim_state
= DIM_STATE_START
;
128 timer_period
= timer_period
* (BL_PWM_COUNT
- bl_pwm_counter
) / BL_PWM_COUNT
;
132 if ((bl_dim_target
> bl_dim_current
) && (bl_cycle_counter
>= fade_in_count
))
135 bl_cycle_counter
= 0;
138 if ((bl_dim_target
< bl_dim_current
) && (bl_cycle_counter
>= fade_out_count
))
141 bl_cycle_counter
= 0;
146 queue_post(&backlight_queue
, BACKLIGHT_UNBOOST_CPU
, NULL
);
148 bl_timer_active
= false;
151 timer_set_period(timer_period
);
154 static void backlight_switch(void)
156 if (bl_dim_target
> (BL_PWM_COUNT
/2))
158 and_l(~0x00020000, &GPIO1_OUT
);
159 bl_dim_current
= BL_PWM_COUNT
;
163 or_l(0x00020000, &GPIO1_OUT
);
168 static void backlight_release_timer(void)
172 bl_timer_active
= false;
176 static void backlight_dim(int value
)
178 /* protect from extraneous calls with the same target value */
179 if (value
== bl_dim_target
)
182 bl_dim_target
= value
;
187 if (timer_register(0, backlight_release_timer
, 1, 0, backlight_isr
))
189 /* Prevent cpu frequency changes while dimming. */
191 bl_timer_active
= true;
197 void backlight_set_fade_in(int index
)
199 fade_in_count
= backlight_fade_value
[index
];
202 void backlight_set_fade_out(int index
)
204 fade_out_count
= backlight_fade_value
[index
];
206 #endif /* (CONFIG_BACKLIGHT == BL_IRIVER_H100) && !defined(SIMULATOR) */
208 static void __backlight_on(void)
212 #elif CONFIG_BACKLIGHT == BL_IRIVER_H100
213 if (fade_in_count
> 0)
214 backlight_dim(BL_PWM_COUNT
);
217 bl_dim_target
= bl_dim_current
= BL_PWM_COUNT
;
218 and_l(~0x00020000, &GPIO1_OUT
);
220 #elif CONFIG_BACKLIGHT == BL_IRIVER_H300
222 or_l(0x00020000, &GPIO1_OUT
);
223 #elif CONFIG_BACKLIGHT == BL_RTC
224 /* Enable square wave */
225 rtc_write(0x0a, rtc_read(0x0a) | 0x40);
226 #elif CONFIG_BACKLIGHT == BL_PA14_LO /* Player */
227 and_b(~0x40, &PADRH
); /* drive and set low */
229 #elif CONFIG_BACKLIGHT == BL_PA14_HI /* Ondio */
230 or_b(0x40, &PADRH
); /* drive it high */
231 #elif CONFIG_BACKLIGHT == BL_GMINI
233 #elif CONFIG_BACKLIGHT == BL_IPOD4G
234 /* brightness full */
235 outl(0x80000000 | (0xff << 16), 0x7000a010);
237 /* set port b bit 3 on */
238 outl(((0x100 | 1) << 3), 0x6000d824);
239 #elif CONFIG_BACKLIGHT==BL_IPODNANO
240 /* set port B03 on */
241 outl(((0x100 | 1) << 3), 0x6000d824);
243 /* set port L07 on */
244 outl(((0x100 | 1) << 7), 0x6000d12c);
245 #elif CONFIG_BACKLIGHT==BL_IRIVER_IFP7XX
250 static void __backlight_off(void)
254 #elif CONFIG_BACKLIGHT == BL_IRIVER_H100
255 if (fade_out_count
> 0)
259 bl_dim_target
= bl_dim_current
= 0;
260 or_l(0x00020000, &GPIO1_OUT
);
262 #elif CONFIG_BACKLIGHT == BL_IRIVER_H300
263 and_l(~0x00020000, &GPIO1_OUT
);
265 #elif CONFIG_BACKLIGHT == BL_RTC
266 /* Disable square wave */
267 rtc_write(0x0a, rtc_read(0x0a) & ~0x40);
268 #elif CONFIG_BACKLIGHT == BL_PA14_LO /* Player */
269 and_b(~0x40, &PAIORH
); /* let it float (up) */
270 #elif CONFIG_BACKLIGHT == BL_PA14_HI /* Ondio */
271 and_b(~0x40, &PADRH
); /* drive it low */
272 #elif CONFIG_BACKLIGHT == BL_GMINI
274 #elif CONFIG_BACKLIGHT == BL_IPOD4G
275 /* fades backlight off on 4g */
276 outl(inl(0x70000084) & ~0x2000000, 0x70000084);
277 outl(0x80000000, 0x7000a010);
278 #elif CONFIG_BACKLIGHT==BL_IPODNANO
279 /* set port B03 off */
280 outl(((0x100 | 0) << 3), 0x6000d824);
282 /* set port L07 off */
283 outl(((0x100 | 0) << 7), 0x6000d12c);
284 #elif CONFIG_BACKLIGHT==BL_IRIVER_IFP7XX
289 #ifdef HAVE_REMOTE_LCD
290 static void __remote_backlight_on(void)
293 sim_remote_backlight(100);
294 #elif defined(IRIVER_H300_SERIES)
295 and_l(~0x00000002, &GPIO1_OUT
);
297 and_l(~0x00000800, &GPIO_OUT
);
301 static void __remote_backlight_off(void)
304 sim_remote_backlight(0);
305 #elif defined(IRIVER_H300_SERIES)
306 or_l(0x00000002, &GPIO1_OUT
);
308 or_l(0x00000800, &GPIO_OUT
);
311 #endif /* HAVE_REMOTE_LCD */
313 void backlight_thread(void)
319 queue_wait(&backlight_queue
, &ev
);
322 #ifdef HAVE_REMOTE_LCD
323 case REMOTE_BACKLIGHT_ON
:
325 if (charger_inserted())
326 remote_backlight_timer
= remote_backlight_timeout_plugged
;
329 remote_backlight_timer
= remote_backlight_timeout
;
331 /* Backlight == OFF in the setting? */
332 if (remote_backlight_timer
< 0)
334 remote_backlight_timer
= 0; /* Disable the timeout */
335 __remote_backlight_off();
339 __remote_backlight_on();
343 case REMOTE_BACKLIGHT_OFF
:
344 __remote_backlight_off();
347 #endif /* HAVE_REMOTE_LCD */
350 if (charger_inserted())
351 backlight_timer
= backlight_timeout_plugged
;
354 backlight_timer
= backlight_timeout
;
356 if (backlight_timer
< 0) /* Backlight == OFF in the setting? */
358 backlight_timer
= 0; /* Disable the timeout */
371 #if (CONFIG_BACKLIGHT == BL_IRIVER_H100) && !defined(SIMULATOR)
372 case BACKLIGHT_UNBOOST_CPU
:
377 case SYS_USB_CONNECTED
:
378 /* Tell the USB thread that we are safe */
379 DEBUGF("backlight_thread got SYS_USB_CONNECTED\n");
380 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
383 case SYS_USB_DISCONNECTED
:
384 usb_acknowledge(SYS_USB_DISCONNECTED_ACK
);
390 static void backlight_tick(void)
393 static bool charger_was_inserted
= false;
394 bool charger_is_inserted
= charger_inserted();
396 if( charger_was_inserted
!= charger_is_inserted
)
399 #ifdef HAVE_REMOTE_LCD
400 remote_backlight_on();
403 charger_was_inserted
= charger_is_inserted
;
404 #endif /* HAVE_CHARGING */
409 if(backlight_timer
== 0)
414 #ifdef HAVE_REMOTE_LCD
415 if(remote_backlight_timer
)
417 remote_backlight_timer
--;
418 if(remote_backlight_timer
== 0)
420 remote_backlight_off();
426 void backlight_init(void)
428 queue_init(&backlight_queue
);
429 create_thread(backlight_thread
, backlight_stack
,
430 sizeof(backlight_stack
), backlight_thread_name
);
431 tick_add_task(backlight_tick
);
434 #elif CONFIG_BACKLIGHT == BL_IRIVER_H100
435 or_l(0x00020000, &GPIO1_ENABLE
);
436 or_l(0x00020000, &GPIO1_FUNCTION
);
437 and_l(~0x00020000, &GPIO1_OUT
); /* Start with the backlight ON */
438 #elif CONFIG_BACKLIGHT == BL_IRIVER_H300
439 or_l(0x00020000, &GPIO1_ENABLE
);
440 or_l(0x00020000, &GPIO1_FUNCTION
);
441 or_l(0x00020000, &GPIO1_OUT
); /* Start with the backlight ON */
442 #elif CONFIG_BACKLIGHT == BL_PA14_LO || CONFIG_BACKLIGHT == BL_PA14_HI
443 PACR1
&= ~0x3000; /* Set PA14 (backlight control) to GPIO */
444 or_b(0x40, &PAIORH
); /* ..and output */
445 #elif CONFIG_BACKLIGHT == BL_GMINI
446 P1CON
|= 0x10; /* P1.4 C-MOS output mode */
449 #ifdef HAVE_REMOTE_LCD
450 remote_backlight_on();
454 void backlight_on(void)
456 queue_post(&backlight_queue
, BACKLIGHT_ON
, NULL
);
459 void backlight_off(void)
461 queue_post(&backlight_queue
, BACKLIGHT_OFF
, NULL
);
464 /* return value in ticks; 0 means always on, <0 means always off */
465 int backlight_get_current_timeout(void)
468 return charger_inserted() ? backlight_timeout_plugged
: backlight_timeout
;
470 return backlight_timeout
;
474 void backlight_set_timeout(int index
)
476 if((unsigned)index
>= sizeof(backlight_timeout_value
))
477 /* if given a weird value, use 0 */
479 backlight_timeout
= HZ
* backlight_timeout_value
[index
];
484 void backlight_set_timeout_plugged(int index
)
486 if((unsigned)index
>= sizeof(backlight_timeout_value
))
487 /* if given a weird value, use 0 */
489 backlight_timeout_plugged
= HZ
* backlight_timeout_value
[index
];
494 #ifdef HAVE_REMOTE_LCD
495 void remote_backlight_on(void)
497 queue_post(&backlight_queue
, REMOTE_BACKLIGHT_ON
, NULL
);
500 void remote_backlight_off(void)
502 queue_post(&backlight_queue
, REMOTE_BACKLIGHT_OFF
, NULL
);
505 void remote_backlight_set_timeout(int index
)
507 if((unsigned)index
>= sizeof(backlight_timeout_value
))
508 /* if given a weird value, use 0 */
510 remote_backlight_timeout
= HZ
* backlight_timeout_value
[index
];
511 remote_backlight_on();
515 void remote_backlight_set_timeout_plugged(int index
)
517 if((unsigned)index
>= sizeof(backlight_timeout_value
))
518 /* if given a weird value, use 0 */
520 remote_backlight_timeout_plugged
= HZ
* backlight_timeout_value
[index
];
521 remote_backlight_on();
524 #endif /* HAVE_REMOTE_LCD */
526 #else /* no backlight, empty dummy functions */
529 void backlight_init(void)
531 #ifdef IRIVER_H300_SERIES
532 or_l(0x00020000, &GPIO1_OUT
);
533 or_l(0x00020000, &GPIO1_ENABLE
);
534 or_l(0x00020000, &GPIO1_FUNCTION
);
539 void backlight_on(void) {}
540 void backlight_off(void) {}
541 void backlight_set_timeout(int index
) {(void)index
;}
542 #ifdef HAVE_REMOTE_LCD
543 void remote_backlight_on(void) {}
544 void remote_backlight_off(void) {}
545 void remote_backlight_set_timeout(int index
) {(void)index
;}
547 #endif /* #ifdef CONFIG_BACKLIGHT */
549 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
550 void backlight_set_brightness(int val
)
552 /* set H300 brightness by changing the PWM
553 accepts 0..15 but note that 0 and 1 give a black display! */
554 unsigned char ucVal
= (unsigned char)(val
& 0x0F);
555 if(val
<MIN_BRIGHTNESS_SETTING
)
556 val
=MIN_BRIGHTNESS_SETTING
;
557 pcf50606_set_bl_pwm(ucVal
);