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) || (CONFIG_BACKLIGHT == BL_IPOD3G)
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_IPODMINI
240 /* set port B03 on */
241 outl(((0x100 | 1) << 3), 0x6000d824);
242 #elif CONFIG_BACKLIGHT==BL_IPODNANO
243 /* set port B03 on */
244 outl(((0x100 | 1) << 3), 0x6000d824);
246 /* set port L07 on */
247 outl(((0x100 | 1) << 7), 0x6000d12c);
248 #elif CONFIG_BACKLIGHT==BL_IPOD3G
250 #elif CONFIG_BACKLIGHT==BL_IRIVER_IFP7XX
255 static void __backlight_off(void)
259 #elif CONFIG_BACKLIGHT == BL_IRIVER_H100
260 if (fade_out_count
> 0)
264 bl_dim_target
= bl_dim_current
= 0;
265 or_l(0x00020000, &GPIO1_OUT
);
267 #elif CONFIG_BACKLIGHT == BL_IRIVER_H300
268 and_l(~0x00020000, &GPIO1_OUT
);
270 #elif CONFIG_BACKLIGHT == BL_RTC
271 /* Disable square wave */
272 rtc_write(0x0a, rtc_read(0x0a) & ~0x40);
273 #elif CONFIG_BACKLIGHT == BL_PA14_LO /* Player */
274 and_b(~0x40, &PAIORH
); /* let it float (up) */
275 #elif CONFIG_BACKLIGHT == BL_PA14_HI /* Ondio */
276 and_b(~0x40, &PADRH
); /* drive it low */
277 #elif CONFIG_BACKLIGHT == BL_GMINI
279 #elif CONFIG_BACKLIGHT == BL_IPOD4G
280 /* fades backlight off on 4g */
281 outl(inl(0x70000084) & ~0x2000000, 0x70000084);
282 outl(0x80000000, 0x7000a010);
283 #elif CONFIG_BACKLIGHT==BL_IPODNANO
284 /* set port B03 off */
285 outl(((0x100 | 0) << 3), 0x6000d824);
287 /* set port L07 off */
288 outl(((0x100 | 0) << 7), 0x6000d12c);
289 #elif CONFIG_BACKLIGHT==BL_IRIVER_IFP7XX
291 #elif CONFIG_BACKLIGHT==BL_IPOD3G
293 #elif CONFIG_BACKLIGHT==BL_IPODMINI
294 /* set port B03 off */
295 outl(((0x100 | 0) << 3), 0x6000d824);
299 #ifdef HAVE_REMOTE_LCD
300 static void __remote_backlight_on(void)
303 sim_remote_backlight(100);
304 #elif defined(IRIVER_H300_SERIES)
305 and_l(~0x00000002, &GPIO1_OUT
);
307 and_l(~0x00000800, &GPIO_OUT
);
311 static void __remote_backlight_off(void)
314 sim_remote_backlight(0);
315 #elif defined(IRIVER_H300_SERIES)
316 or_l(0x00000002, &GPIO1_OUT
);
318 or_l(0x00000800, &GPIO_OUT
);
321 #endif /* HAVE_REMOTE_LCD */
323 void backlight_thread(void)
329 queue_wait(&backlight_queue
, &ev
);
332 #ifdef HAVE_REMOTE_LCD
333 case REMOTE_BACKLIGHT_ON
:
335 if (charger_inserted())
336 remote_backlight_timer
= remote_backlight_timeout_plugged
;
339 remote_backlight_timer
= remote_backlight_timeout
;
341 /* Backlight == OFF in the setting? */
342 if (remote_backlight_timer
< 0)
344 remote_backlight_timer
= 0; /* Disable the timeout */
345 __remote_backlight_off();
349 __remote_backlight_on();
353 case REMOTE_BACKLIGHT_OFF
:
354 __remote_backlight_off();
357 #endif /* HAVE_REMOTE_LCD */
360 if (charger_inserted())
361 backlight_timer
= backlight_timeout_plugged
;
364 backlight_timer
= backlight_timeout
;
366 if (backlight_timer
< 0) /* Backlight == OFF in the setting? */
368 backlight_timer
= 0; /* Disable the timeout */
381 #if (CONFIG_BACKLIGHT == BL_IRIVER_H100) && !defined(SIMULATOR)
382 case BACKLIGHT_UNBOOST_CPU
:
387 case SYS_USB_CONNECTED
:
388 /* Tell the USB thread that we are safe */
389 DEBUGF("backlight_thread got SYS_USB_CONNECTED\n");
390 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
393 case SYS_USB_DISCONNECTED
:
394 usb_acknowledge(SYS_USB_DISCONNECTED_ACK
);
400 static void backlight_tick(void)
403 static bool charger_was_inserted
= false;
404 bool charger_is_inserted
= charger_inserted();
406 if( charger_was_inserted
!= charger_is_inserted
)
409 #ifdef HAVE_REMOTE_LCD
410 remote_backlight_on();
413 charger_was_inserted
= charger_is_inserted
;
414 #endif /* HAVE_CHARGING */
419 if(backlight_timer
== 0)
424 #ifdef HAVE_REMOTE_LCD
425 if(remote_backlight_timer
)
427 remote_backlight_timer
--;
428 if(remote_backlight_timer
== 0)
430 remote_backlight_off();
436 void backlight_init(void)
438 queue_init(&backlight_queue
);
439 create_thread(backlight_thread
, backlight_stack
,
440 sizeof(backlight_stack
), backlight_thread_name
);
441 tick_add_task(backlight_tick
);
444 #elif CONFIG_BACKLIGHT == BL_IRIVER_H100
445 or_l(0x00020000, &GPIO1_ENABLE
);
446 or_l(0x00020000, &GPIO1_FUNCTION
);
447 and_l(~0x00020000, &GPIO1_OUT
); /* Start with the backlight ON */
448 #elif CONFIG_BACKLIGHT == BL_IRIVER_H300
449 or_l(0x00020000, &GPIO1_ENABLE
);
450 or_l(0x00020000, &GPIO1_FUNCTION
);
451 or_l(0x00020000, &GPIO1_OUT
); /* Start with the backlight ON */
452 #elif CONFIG_BACKLIGHT == BL_PA14_LO || CONFIG_BACKLIGHT == BL_PA14_HI
453 PACR1
&= ~0x3000; /* Set PA14 (backlight control) to GPIO */
454 or_b(0x40, &PAIORH
); /* ..and output */
455 #elif CONFIG_BACKLIGHT == BL_GMINI
456 P1CON
|= 0x10; /* P1.4 C-MOS output mode */
459 #ifdef HAVE_REMOTE_LCD
460 remote_backlight_on();
464 void backlight_on(void)
466 queue_post(&backlight_queue
, BACKLIGHT_ON
, NULL
);
469 void backlight_off(void)
471 queue_post(&backlight_queue
, BACKLIGHT_OFF
, NULL
);
474 /* return value in ticks; 0 means always on, <0 means always off */
475 int backlight_get_current_timeout(void)
478 return charger_inserted() ? backlight_timeout_plugged
: backlight_timeout
;
480 return backlight_timeout
;
484 void backlight_set_timeout(int index
)
486 if((unsigned)index
>= sizeof(backlight_timeout_value
))
487 /* if given a weird value, use 0 */
489 backlight_timeout
= HZ
* backlight_timeout_value
[index
];
494 void backlight_set_timeout_plugged(int index
)
496 if((unsigned)index
>= sizeof(backlight_timeout_value
))
497 /* if given a weird value, use 0 */
499 backlight_timeout_plugged
= HZ
* backlight_timeout_value
[index
];
504 #ifdef HAVE_REMOTE_LCD
505 void remote_backlight_on(void)
507 queue_post(&backlight_queue
, REMOTE_BACKLIGHT_ON
, NULL
);
510 void remote_backlight_off(void)
512 queue_post(&backlight_queue
, REMOTE_BACKLIGHT_OFF
, NULL
);
515 void remote_backlight_set_timeout(int index
)
517 if((unsigned)index
>= sizeof(backlight_timeout_value
))
518 /* if given a weird value, use 0 */
520 remote_backlight_timeout
= HZ
* backlight_timeout_value
[index
];
521 remote_backlight_on();
525 void remote_backlight_set_timeout_plugged(int index
)
527 if((unsigned)index
>= sizeof(backlight_timeout_value
))
528 /* if given a weird value, use 0 */
530 remote_backlight_timeout_plugged
= HZ
* backlight_timeout_value
[index
];
531 remote_backlight_on();
534 #endif /* HAVE_REMOTE_LCD */
536 #else /* no backlight, empty dummy functions */
539 void backlight_init(void)
541 #ifdef IRIVER_H300_SERIES
542 or_l(0x00020000, &GPIO1_OUT
);
543 or_l(0x00020000, &GPIO1_ENABLE
);
544 or_l(0x00020000, &GPIO1_FUNCTION
);
549 void backlight_on(void) {}
550 void backlight_off(void) {}
551 void backlight_set_timeout(int index
) {(void)index
;}
552 #ifdef HAVE_REMOTE_LCD
553 void remote_backlight_on(void) {}
554 void remote_backlight_off(void) {}
555 void remote_backlight_set_timeout(int index
) {(void)index
;}
557 #endif /* #ifdef CONFIG_BACKLIGHT */
559 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
560 #ifdef IRIVER_H300_SERIES
561 void backlight_set_brightness(int val
)
563 /* set H300 brightness by changing the PWM
564 accepts 0..15 but note that 0 and 1 give a black display! */
566 if(val
<MIN_BRIGHTNESS_SETTING
)
567 val
=MIN_BRIGHTNESS_SETTING
;
569 /* shift one bit left */
575 /* disable IRQs while bitbanging */
576 int old_irq_level
= set_irq_level(HIGHEST_IRQ_LEVEL
);
578 pcf50606_write(0x35, val
);
580 /* enable IRQs again */
581 set_irq_level(old_irq_level
);