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.tar.gz
rockbox-62ff88b71735c01384e23d915bf1c29167425cf5.zip
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 9250f320b9..4c421e50fc 100644
--- a/firmware/target/arm/as3525/kernel-as3525.c
+++ b/firmware/target/arm/as3525/kernel-as3525.c
@@ -36,7 +36,7 @@
36/* The scrollwheel is polled every 5 ms (the tick tasks only every 10) */ 36/* The scrollwheel is polled every 5 ms (the tick tasks only every 10) */
37static int poll_scrollwheel = 0; 37static int poll_scrollwheel = 0;
38 38
39void INT_TIMER2(void) 39static inline void do_scrollwheel(void)
40{ 40{
41 if (!poll_scrollwheel) 41 if (!poll_scrollwheel)
42 call_tick_tasks(); /* Run through the list of tick tasks 42 call_tick_tasks(); /* Run through the list of tick tasks
@@ -48,16 +48,131 @@ void INT_TIMER2(void)
48 } 48 }
49 49
50 poll_scrollwheel ^= 1; 50 poll_scrollwheel ^= 1;
51}
52#else
53static inline void do_scrollwheel(void)
54{
55 call_tick_tasks(); /* Run through the list of tick tasks */
56}
57#endif
58
59#if defined(SANSA_C200V2)
60#include "backlight-target.h"
61
62static int timer2_cycles_per_tick = 0;
63static int timer2_cycles_pwmon = 0;
64static int timer2_cycles_pwmoff = 0;
65static int timer2_pwm_state = 0;
66static int timer2_pwm_on = 0;
67
68void _set_timer2_pwm_ratio(int ratio)
69{
70 int cycles = timer2_cycles_per_tick;
71
72 /*
73 * Rather arbitrary limits, but since the CPU
74 * needs some to time in the interrupt handler
75 * there sure is some limit.
76 * More specifically, if the cycles needed to do
77 * the pwm handling are more than the reloaded counter needs
78 * to reach 0 again it will reload to the old value most
79 * likely leading to a (slight) slowdown in tick rate.
80 */
81
82 if (ratio < 10) {
83 /*
84 * Permanent off, reduce interrupt rate to save power
85 */
86 TIMER2_BGLOAD = cycles;
87 timer2_pwm_on = 0;
88 _backlight_pwm(0);
89 return;
90 }
91
92 if (ratio > 990) {
93 /*
94 * Permanent on, reduce interrupt rate to save power
95 */
96 TIMER2_BGLOAD = cycles;
97 timer2_pwm_on = 0;
98 _backlight_pwm(1);
99 return;
100 }
101
102 timer2_cycles_pwmon = cycles*ratio/1000;
103 timer2_cycles_pwmoff = cycles*(1000-ratio)/1000;
104
105 if (timer2_pwm_on == 0) {
106 timer2_pwm_state = 0;
107 timer2_pwm_on = 1;
108 TIMER2_BGLOAD = timer2_cycles_pwmoff;
109 }
110}
111
112static void set_timer2_cycles_per_tick(int cycles)
113{
114 timer2_cycles_per_tick = cycles;
115}
116
117static inline void do_sw_pwm(void)
118{
119 if (!timer2_pwm_on) {
120 do_scrollwheel(); /* Handle scrollwheel and tick tasks */
121 TIMER2_INTCLR = 0; /* clear interrupt */
122 return;
123 }
124
125 timer2_pwm_state ^= 1;
126 if (timer2_pwm_state) {
127 TIMER2_BGLOAD = timer2_cycles_pwmoff;
128 _backlight_pwm(1);
129 /*
130 * Always do scrollwheel and tick tasks during the longer cycle for safety,
131 * since the short cycle can be quite short.
132 * (minimum: 1us if ratio is 10 or 990 or 0.5us with scrollwheel,
133 * or just about 6000 clock cycles at 60MHz)
134 */
135 if (timer2_cycles_pwmon > timer2_cycles_pwmoff)
136 do_scrollwheel(); /* Handle scrollwheel and tick tasks */
137 } else {
138 TIMER2_BGLOAD = timer2_cycles_pwmon;
139 _backlight_pwm(0);
140 if (!(timer2_cycles_pwmon > timer2_cycles_pwmoff))
141 do_scrollwheel(); /* Handle scrollwheel and tick tasks */
142 }
143
51 TIMER2_INTCLR = 0; /* clear interrupt */ 144 TIMER2_INTCLR = 0; /* clear interrupt */
52} 145}
53#else 146#else
147static inline void do_sw_pwm(void)
148{
149 do_scrollwheel(); /* Handle scrollwheel and tick tasks */
150}
151
152static void set_timer2_cycles_per_tick(int cycles)
153{
154 (void)cycles;
155}
156#endif
157
158
54void INT_TIMER2(void) 159void INT_TIMER2(void)
55{ 160{
56 call_tick_tasks(); /* Run through the list of tick tasks */ 161 /*
162 * Timer is stacked as follows:
163 * Lowest layer: Software PWM (if configured)
164 * Alternates timer2 reload value to implement
165 * software pwm at 100Hz (no scrollwheel)
166 * or 200Hz (scrollwheel) with variable pulse width 1% to 99%
167 * Middle layer: Scrollwheel handling (if configured, 200Hz)
168 * Alternate between polling scrollwheel and running tick
169 * tasks (includes scrollwheel polling).
170 * Top layer: Run tick tasks at 100Hz
171 */
172 do_sw_pwm();
57 173
58 TIMER2_INTCLR = 0; /* clear interrupt */ 174 TIMER2_INTCLR = 0; /* clear interrupt */
59} 175}
60#endif
61 176
62void tick_start(unsigned int interval_in_ms) 177void tick_start(unsigned int interval_in_ms)
63{ 178{
@@ -66,6 +181,7 @@ void tick_start(unsigned int interval_in_ms)
66 CGU_PERI |= CGU_TIMER2_CLOCK_ENABLE; /* enable peripheral */ 181 CGU_PERI |= CGU_TIMER2_CLOCK_ENABLE; /* enable peripheral */
67 VIC_INT_ENABLE = INTERRUPT_TIMER2; /* enable interrupt */ 182 VIC_INT_ENABLE = INTERRUPT_TIMER2; /* enable interrupt */
68 183
184 set_timer2_cycles_per_tick(cycles);
69 TIMER2_LOAD = TIMER2_BGLOAD = cycles; /* timer period */ 185 TIMER2_LOAD = TIMER2_BGLOAD = cycles; /* timer period */
70 186
71 /* /!\ bit 4 (reserved) must not be modified 187 /* /!\ 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 d38c068ca2..e094cca8fe 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 @@
27#include "as3514.h" 27#include "as3514.h"
28 28
29int buttonlight_is_on = 0; 29int buttonlight_is_on = 0;
30int backlight_is_on = 0;
31static int backlight_level = 0;
32
33/* logarithmic lookup table for brightness s*/
34static const int brightness_table[MAX_BRIGHTNESS_SETTING+1] = {
35 0, 21, 47, 78, 118, 165, 224, 296, 386, 495, 630, 796, 1000
36};
37
38static void _ll_backlight_on(void)
39{
40 GPIOA_PIN(5) = 1<<5;
41}
42
43static void _ll_backlight_off(void)
44{
45 GPIOA_PIN(5) = 0;
46}
47
48void _backlight_pwm(int on)
49{
50 if (on) {
51 _ll_backlight_on();
52 } else {
53 _ll_backlight_off();
54 }
55}
30 56
31bool _backlight_init(void) 57bool _backlight_init(void)
32{ 58{
@@ -36,6 +62,8 @@ bool _backlight_init(void)
36 62
37void _backlight_set_brightness(int brightness) 63void _backlight_set_brightness(int brightness)
38{ 64{
65 backlight_level = brightness_table[brightness];
66
39 if (brightness > 0) 67 if (brightness > 0)
40 _backlight_on(); 68 _backlight_on();
41 else 69 else
@@ -47,12 +75,17 @@ void _backlight_on(void)
47#ifdef HAVE_LCD_ENABLE 75#ifdef HAVE_LCD_ENABLE
48 lcd_enable(true); /* power on lcd + visible display */ 76 lcd_enable(true); /* power on lcd + visible display */
49#endif 77#endif
50 GPIOA_PIN(5) = 1<<5; 78 if (!backlight_is_on)
79 _ll_backlight_on();
80 _set_timer2_pwm_ratio(backlight_level);
81 backlight_is_on = 1;
51} 82}
52 83
53void _backlight_off(void) 84void _backlight_off(void)
54{ 85{
55 GPIOA_PIN(5) = 0; 86 backlight_is_on = 0;
87 _set_timer2_pwm_ratio(0);
88 _ll_backlight_off();
56#ifdef HAVE_LCD_ENABLE 89#ifdef HAVE_LCD_ENABLE
57 lcd_enable(false); /* power off visible display */ 90 lcd_enable(false); /* power off visible display */
58#endif 91#endif
diff --git a/firmware/target/arm/as3525/sansa-c200v2/backlight-target.h b/firmware/target/arm/as3525/sansa-c200v2/backlight-target.h
index 84a6ea6179..c09e759138 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 @@
24#include <stdbool.h> 24#include <stdbool.h>
25 25
26bool _backlight_init(void); 26bool _backlight_init(void);
27void _backlight_pwm(int on);
27void _backlight_on(void); 28void _backlight_on(void);
28void _backlight_off(void); 29void _backlight_off(void);
29void _backlight_set_brightness(int brightness); 30void _backlight_set_brightness(int brightness);
@@ -31,4 +32,10 @@ int __backlight_is_on(void);
31 32
32void _buttonlight_on(void); 33void _buttonlight_on(void);
33void _buttonlight_off(void); 34void _buttonlight_off(void);
35
36/*
37 * FIXME: This may be better off in kernel.h, but...
38 */
39void _set_timer2_pwm_ratio(int ratio);
40
34#endif 41#endif