summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Diedrich <ranma+coreboot@tdiedrich.de>2010-03-23 05:27:32 +0000
committerTobias Diedrich <ranma+coreboot@tdiedrich.de>2010-03-23 05:27:32 +0000
commit62ff88b71735c01384e23d915bf1c29167425cf5 (patch)
tree7b09c63edf747f7dbbe5f960ce734d5a50647798
parent47ab95904efe238568e4cc66f0d3aacd9e7a8c10 (diff)
downloadrockbox-62ff88b71735c01384e23d915bf1c29167425cf5.zip
rockbox-62ff88b71735c01384e23d915bf1c29167425cf5.tar.gz
rockbox-62ff88b71735c01384e23d915bf1c29167425cf5.tar.bz2
rockbox-62ff88b71735c01384e23d915bf1c29167425cf5.tar.xz
Implement software pwm to control c200v2 display brightness.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25300 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/target/arm/as3525/kernel-as3525.c122
-rw-r--r--firmware/target/arm/as3525/sansa-c200v2/backlight-c200v2.c37
-rw-r--r--firmware/target/arm/as3525/sansa-c200v2/backlight-target.h7
3 files changed, 161 insertions, 5 deletions
diff --git a/firmware/target/arm/as3525/kernel-as3525.c b/firmware/target/arm/as3525/kernel-as3525.c
index 9250f32..4c421e5 100644
--- a/firmware/target/arm/as3525/kernel-as3525.c
+++ b/firmware/target/arm/as3525/kernel-as3525.c
@@ -36,7 +36,7 @@
/* The scrollwheel is polled every 5 ms (the tick tasks only every 10) */
static int poll_scrollwheel = 0;
-void INT_TIMER2(void)
+static inline void do_scrollwheel(void)
{
if (!poll_scrollwheel)
call_tick_tasks(); /* Run through the list of tick tasks
@@ -48,16 +48,131 @@ void INT_TIMER2(void)
}
poll_scrollwheel ^= 1;
+}
+#else
+static inline void do_scrollwheel(void)
+{
+ call_tick_tasks(); /* Run through the list of tick tasks */
+}
+#endif
+
+#if defined(SANSA_C200V2)
+#include "backlight-target.h"
+
+static int timer2_cycles_per_tick = 0;
+static int timer2_cycles_pwmon = 0;
+static int timer2_cycles_pwmoff = 0;
+static int timer2_pwm_state = 0;
+static int timer2_pwm_on = 0;
+
+void _set_timer2_pwm_ratio(int ratio)
+{
+ int cycles = timer2_cycles_per_tick;
+
+ /*
+ * Rather arbitrary limits, but since the CPU
+ * needs some to time in the interrupt handler
+ * there sure is some limit.
+ * More specifically, if the cycles needed to do
+ * the pwm handling are more than the reloaded counter needs
+ * to reach 0 again it will reload to the old value most
+ * likely leading to a (slight) slowdown in tick rate.
+ */
+
+ if (ratio < 10) {
+ /*
+ * Permanent off, reduce interrupt rate to save power
+ */
+ TIMER2_BGLOAD = cycles;
+ timer2_pwm_on = 0;
+ _backlight_pwm(0);
+ return;
+ }
+
+ if (ratio > 990) {
+ /*
+ * Permanent on, reduce interrupt rate to save power
+ */
+ TIMER2_BGLOAD = cycles;
+ timer2_pwm_on = 0;
+ _backlight_pwm(1);
+ return;
+ }
+
+ timer2_cycles_pwmon = cycles*ratio/1000;
+ timer2_cycles_pwmoff = cycles*(1000-ratio)/1000;
+
+ if (timer2_pwm_on == 0) {
+ timer2_pwm_state = 0;
+ timer2_pwm_on = 1;
+ TIMER2_BGLOAD = timer2_cycles_pwmoff;
+ }
+}
+
+static void set_timer2_cycles_per_tick(int cycles)
+{
+ timer2_cycles_per_tick = cycles;
+}
+
+static inline void do_sw_pwm(void)
+{
+ if (!timer2_pwm_on) {
+ do_scrollwheel(); /* Handle scrollwheel and tick tasks */
+ TIMER2_INTCLR = 0; /* clear interrupt */
+ return;
+ }
+
+ timer2_pwm_state ^= 1;
+ if (timer2_pwm_state) {
+ TIMER2_BGLOAD = timer2_cycles_pwmoff;
+ _backlight_pwm(1);
+ /*
+ * Always do scrollwheel and tick tasks during the longer cycle for safety,
+ * since the short cycle can be quite short.
+ * (minimum: 1us if ratio is 10 or 990 or 0.5us with scrollwheel,
+ * or just about 6000 clock cycles at 60MHz)
+ */
+ if (timer2_cycles_pwmon > timer2_cycles_pwmoff)
+ do_scrollwheel(); /* Handle scrollwheel and tick tasks */
+ } else {
+ TIMER2_BGLOAD = timer2_cycles_pwmon;
+ _backlight_pwm(0);
+ if (!(timer2_cycles_pwmon > timer2_cycles_pwmoff))
+ do_scrollwheel(); /* Handle scrollwheel and tick tasks */
+ }
+
TIMER2_INTCLR = 0; /* clear interrupt */
}
#else
+static inline void do_sw_pwm(void)
+{
+ do_scrollwheel(); /* Handle scrollwheel and tick tasks */
+}
+
+static void set_timer2_cycles_per_tick(int cycles)
+{
+ (void)cycles;
+}
+#endif
+
+
void INT_TIMER2(void)
{
- call_tick_tasks(); /* Run through the list of tick tasks */
+ /*
+ * Timer is stacked as follows:
+ * Lowest layer: Software PWM (if configured)
+ * Alternates timer2 reload value to implement
+ * software pwm at 100Hz (no scrollwheel)
+ * or 200Hz (scrollwheel) with variable pulse width 1% to 99%
+ * Middle layer: Scrollwheel handling (if configured, 200Hz)
+ * Alternate between polling scrollwheel and running tick
+ * tasks (includes scrollwheel polling).
+ * Top layer: Run tick tasks at 100Hz
+ */
+ do_sw_pwm();
TIMER2_INTCLR = 0; /* clear interrupt */
}
-#endif
void tick_start(unsigned int interval_in_ms)
{
@@ -66,6 +181,7 @@ void tick_start(unsigned int interval_in_ms)
CGU_PERI |= CGU_TIMER2_CLOCK_ENABLE; /* enable peripheral */
VIC_INT_ENABLE = INTERRUPT_TIMER2; /* enable interrupt */
+ set_timer2_cycles_per_tick(cycles);
TIMER2_LOAD = TIMER2_BGLOAD = cycles; /* timer period */
/* /!\ bit 4 (reserved) must not be modified
diff --git a/firmware/target/arm/as3525/sansa-c200v2/backlight-c200v2.c b/firmware/target/arm/as3525/sansa-c200v2/backlight-c200v2.c
index d38c068..e094cca 100644
--- a/firmware/target/arm/as3525/sansa-c200v2/backlight-c200v2.c
+++ b/firmware/target/arm/as3525/sansa-c200v2/backlight-c200v2.c
@@ -27,6 +27,32 @@
#include "as3514.h"
int buttonlight_is_on = 0;
+int backlight_is_on = 0;
+static int backlight_level = 0;
+
+/* logarithmic lookup table for brightness s*/
+static const int brightness_table[MAX_BRIGHTNESS_SETTING+1] = {
+ 0, 21, 47, 78, 118, 165, 224, 296, 386, 495, 630, 796, 1000
+};
+
+static void _ll_backlight_on(void)
+{
+ GPIOA_PIN(5) = 1<<5;
+}
+
+static void _ll_backlight_off(void)
+{
+ GPIOA_PIN(5) = 0;
+}
+
+void _backlight_pwm(int on)
+{
+ if (on) {
+ _ll_backlight_on();
+ } else {
+ _ll_backlight_off();
+ }
+}
bool _backlight_init(void)
{
@@ -36,6 +62,8 @@ bool _backlight_init(void)
void _backlight_set_brightness(int brightness)
{
+ backlight_level = brightness_table[brightness];
+
if (brightness > 0)
_backlight_on();
else
@@ -47,12 +75,17 @@ void _backlight_on(void)
#ifdef HAVE_LCD_ENABLE
lcd_enable(true); /* power on lcd + visible display */
#endif
- GPIOA_PIN(5) = 1<<5;
+ if (!backlight_is_on)
+ _ll_backlight_on();
+ _set_timer2_pwm_ratio(backlight_level);
+ backlight_is_on = 1;
}
void _backlight_off(void)
{
- GPIOA_PIN(5) = 0;
+ backlight_is_on = 0;
+ _set_timer2_pwm_ratio(0);
+ _ll_backlight_off();
#ifdef HAVE_LCD_ENABLE
lcd_enable(false); /* power off visible display */
#endif
diff --git a/firmware/target/arm/as3525/sansa-c200v2/backlight-target.h b/firmware/target/arm/as3525/sansa-c200v2/backlight-target.h
index 84a6ea6..c09e759 100644
--- a/firmware/target/arm/as3525/sansa-c200v2/backlight-target.h
+++ b/firmware/target/arm/as3525/sansa-c200v2/backlight-target.h
@@ -24,6 +24,7 @@
#include <stdbool.h>
bool _backlight_init(void);
+void _backlight_pwm(int on);
void _backlight_on(void);
void _backlight_off(void);
void _backlight_set_brightness(int brightness);
@@ -31,4 +32,10 @@ int __backlight_is_on(void);
void _buttonlight_on(void);
void _buttonlight_off(void);
+
+/*
+ * FIXME: This may be better off in kernel.h, but...
+ */
+void _set_timer2_pwm_ratio(int ratio);
+
#endif