diff options
author | Karl Kurbjun <kkurbjun@gmail.com> | 2008-05-14 00:26:28 +0000 |
---|---|---|
committer | Karl Kurbjun <kkurbjun@gmail.com> | 2008-05-14 00:26:28 +0000 |
commit | 6e322c878695e9b6dbf5620feda76315a523cc43 (patch) | |
tree | fa752c8f5419c4c27dabcc53dedba2b0ad4f9f97 | |
parent | f7e0e6bb1cfc079cfbf18ce3224442be26ba46f2 (diff) | |
download | rockbox-6e322c878695e9b6dbf5620feda76315a523cc43.tar.gz rockbox-6e322c878695e9b6dbf5620feda76315a523cc43.zip |
Reduce power consumed on the F/X by as much as 12% when the LCD is disabled. Timing is tighter on the SPI interface, if the screen does not come up let me know and we can space it out more - Works on the devices I tested. There will be a brief time (around 15ms) that the screen is all white after coming back on.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17498 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c | 249 |
1 files changed, 144 insertions, 105 deletions
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c index 90ab145873..5c666b43f1 100644 --- a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c +++ b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c | |||
@@ -66,17 +66,55 @@ inline void delay_cycles(volatile int delay) | |||
66 | while(delay>0) delay--; | 66 | while(delay>0) delay--; |
67 | } | 67 | } |
68 | 68 | ||
69 | void SPI_LCD_CS(bool select) | 69 | void LCD_CTRL_setup(void) |
70 | { | 70 | { |
71 | delay_cycles(0x4FFF); | 71 | /* ENVID = 0, BPPMODE = 16 bpp, PNRMODE = TFT, MMODE = Each Frame, CLKVAL = 8 */ |
72 | LCDCON1 = 0x878; | ||
72 | 73 | ||
73 | GPBCON&=~0x30000; | 74 | /* VCPW = 1, VFPD = 5, LINEVAL = 319, VBPD = 7 */ |
74 | GPBCON|=0x10000; | 75 | LCDCON2 = 0x74FC141; |
76 | |||
77 | /* HFPD = 9, HOZVAL = 239, HBPD = 7 */ | ||
78 | LCDCON3 = 0x38EF09; | ||
75 | 79 | ||
76 | if(select) | 80 | /* HSPW = 7 */ |
77 | GPBDAT|=0x100; | 81 | LCDCON4 = 7; |
78 | else | 82 | |
79 | GPBDAT&=~0x100; | 83 | /* HWSWP = 1, INVVFRAM = 1, INVVLINE = 1, FRM565 = 1, All others = 0 */ |
84 | LCDCON5 = 0xB01; | ||
85 | |||
86 | LCDSADDR1 = (LCDBANK((unsigned)FRAME) << 21) | (LCDBASEU((unsigned)FRAME)); | ||
87 | LCDSADDR2 = LCDBASEL((unsigned)FRAME); | ||
88 | LCDSADDR3 = 0x000000F0; | ||
89 | } | ||
90 | |||
91 | void LCD_CTRL_clock(bool onoff) | ||
92 | { | ||
93 | if(onoff) | ||
94 | { | ||
95 | GPCCON &= ~0xFFF000FC; | ||
96 | GPDCON &= ~0xFFF0FFF0; | ||
97 | |||
98 | GPCCON |= 0xAAA000A8; | ||
99 | GPCUP |= 0xFC0E; | ||
100 | |||
101 | GPDCON |= 0xAAA0AAA0; | ||
102 | GPDUP |= 0xFCFC; | ||
103 | |||
104 | s3c_regset(&CLKCON, 0x20); /* enable LCD clock */ | ||
105 | LCDCON1 |=0x01; | ||
106 | } | ||
107 | else | ||
108 | { | ||
109 | GPCCON &= ~0xFFF000FC; | ||
110 | GPCUP &= ~0xFC0E; | ||
111 | |||
112 | GPDCON &= ~0xFFF0FFF0; | ||
113 | GPDUP &= ~0xFCFC; | ||
114 | |||
115 | LCDCON1 &= ~1; /* Must diable first or bus may freeze */ | ||
116 | s3c_regclr(&CLKCON, 0x20); /* disable LCD clock */ | ||
117 | } | ||
80 | } | 118 | } |
81 | 119 | ||
82 | void reset_LCD(bool reset) | 120 | void reset_LCD(bool reset) |
@@ -89,7 +127,7 @@ void reset_LCD(bool reset) | |||
89 | GPBDAT&=~0x80; | 127 | GPBDAT&=~0x80; |
90 | } | 128 | } |
91 | 129 | ||
92 | void SPI_Send_Bytes(const unsigned char *array, int count) | 130 | void LCD_SPI_send(const unsigned char *array, int count) |
93 | { | 131 | { |
94 | while (count--) | 132 | while (count--) |
95 | { | 133 | { |
@@ -98,97 +136,80 @@ void SPI_Send_Bytes(const unsigned char *array, int count) | |||
98 | } | 136 | } |
99 | } | 137 | } |
100 | 138 | ||
101 | void Setup_LCD_SPI(void) | 139 | void LCD_SPI_SS(bool select) |
102 | { | 140 | { |
103 | s3c_regset(&CLKCON, 0x40000); | 141 | delay_cycles(0x4FFF); |
104 | SPI_LCD_CS(false); | ||
105 | SPCON0=0x3E; | ||
106 | SPPRE0=24; | ||
107 | } | ||
108 | 142 | ||
109 | void Setup_LCD_CTRL(void) | 143 | GPBCON&=~0x30000; |
110 | { | 144 | GPBCON|=0x10000; |
111 | /* ENVID = 0, BPPMODE = 16 bpp, PNRMODE = TFT, MMODE = Each Frame, CLKVAL = 8 */ | ||
112 | LCDCON1 = 0x878; | ||
113 | 145 | ||
114 | /* VCPW = 1, VFPD = 5, LINEVAL = 319, VBPD = 7 */ | 146 | if(select) |
115 | LCDCON2 = 0x74FC141; | 147 | GPBDAT|=0x100; |
116 | 148 | else | |
117 | /* HFPD = 9, HOZVAL = 239, HBPD = 7 */ | 149 | GPBDAT&=~0x100; |
118 | LCDCON3 = 0x38EF09; | 150 | } |
119 | 151 | ||
120 | /* HSPW = 7 */ | 152 | void LCD_SPI_start(void) |
121 | LCDCON4 = 7; | 153 | { |
122 | 154 | s3c_regset(&CLKCON, 0x40000); /* enable SPI clock */ | |
123 | /* HWSWP = 1, INVVFRAM = 1, INVVLINE = 1, FRM565 = 1, All others = 0 */ | 155 | LCD_SPI_SS(false); |
124 | LCDCON5 = 0xB01; | 156 | SPCON0=0x3E; |
157 | SPPRE0=24; | ||
125 | 158 | ||
126 | LCDSADDR1 = (LCDBANK((unsigned)FRAME) << 21) | (LCDBASEU((unsigned)FRAME)); | 159 | reset_LCD(true); |
127 | LCDSADDR2 = LCDBASEL((unsigned)FRAME); | 160 | LCD_SPI_SS(true); |
128 | LCDSADDR3 = 0x000000F0; | ||
129 | } | 161 | } |
130 | 162 | ||
131 | /* LCD init */ | 163 | void LCD_SPI_stop(void) |
132 | void lcd_init_device(void) | ||
133 | { | 164 | { |
134 | #ifdef BOOTLOADER | 165 | LCD_SPI_SS(false); |
135 | int i; | ||
136 | /* When the Rockbox bootloader starts, we are changing framebuffer address, | ||
137 | but we don't want what's shown on the LCD to change until we do an | ||
138 | lcd_update(), so copy the data from the old framebuffer to the new one */ | ||
139 | unsigned short *buf = (unsigned short*)FRAME; | ||
140 | |||
141 | memcpy(FRAME, (short *)((LCDSADDR1)<<1), 320*240*2); | ||
142 | |||
143 | /* The Rockbox bootloader is transitioning from RGB555I to RGB565 mode | ||
144 | so convert the frambuffer data accordingly */ | ||
145 | for(i=0; i< 320*240; i++){ | ||
146 | *buf = ((*buf>>1) & 0x1F) | (*buf & 0xffc0); | ||
147 | buf++; | ||
148 | } | ||
149 | #endif | ||
150 | |||
151 | /* Set pins up */ | ||
152 | GPCCON |= 0xAAA000A8; | ||
153 | GPCUP |= 0xFC0E; | ||
154 | 166 | ||
155 | GPDCON |= 0xAAA0AAA0; | 167 | SPCON0 &= ~0x10; |
156 | GPDUP |= 0xFCFC; | 168 | s3c_regclr(&CLKCON, 0x40000); /* disable SPI clock */ |
169 | } | ||
157 | 170 | ||
158 | GPHUP &= 0x600; | 171 | void LCD_SPI_powerdown(void) |
172 | { | ||
173 | const unsigned char powerdncmd[] = | ||
174 | { | ||
175 | 0,0x04,1,0x00 | ||
176 | }; | ||
159 | 177 | ||
160 | GPECON |= 0x0A800000; | 178 | LCD_SPI_start(); |
161 | GPEUP |= 0x3800; | ||
162 | 179 | ||
163 | GPBUP |= 0x181; | 180 | LCD_SPI_send(powerdncmd, sizeof(powerdncmd)); |
164 | 181 | ||
165 | #if !defined(BOOTLOADER) | 182 | LCD_SPI_stop(); |
166 | lcd_poweroff = false; | ||
167 | #endif | ||
168 | 183 | ||
169 | s3c_regset(&CLKCON, 0x20); /* enable LCD clock */ | 184 | reset_LCD(false); /* This makes a big difference on power */ |
185 | LCD_CTRL_clock(false); | ||
186 | } | ||
170 | 187 | ||
171 | Setup_LCD_SPI(); | 188 | void LCD_SPI_powerup(void) |
189 | { | ||
190 | const unsigned char powerupcmd[] = | ||
191 | { | ||
192 | 0,0x04,1,0x01 | ||
193 | }; | ||
172 | 194 | ||
173 | Setup_LCD_CTRL(); | 195 | LCD_CTRL_clock(true); |
174 | 196 | ||
175 | delay_cycles(0xA000); | 197 | LCD_SPI_start(); |
176 | 198 | ||
177 | reset_LCD(true); | 199 | LCD_SPI_send(powerupcmd, sizeof(powerupcmd)); |
178 | LCDCON1|=0x01; | ||
179 | 200 | ||
180 | delay_cycles(0x80000); | 201 | LCD_SPI_stop(); |
202 | } | ||
181 | 203 | ||
182 | #if 0 | 204 | void LCD_SPI_init(void) |
183 | /* Setup the appropriate screen modes */ | 205 | { |
184 | TCONSEL= 0xCE6; | 206 | /* SPI data - Right now we are not sure what each of these SPI writes is |
185 | #endif | 207 | * actually telling the lcd. Many thanks to Alex Gerchanovsky for |
186 | 208 | * discovering them. | |
187 | /* SPI data - Right now we are not sure what each of these SPI writes is actually | ||
188 | * telling the lcd. Many thanks to Alex Gerchanovsky for discovering them. | ||
189 | * | 209 | * |
190 | * This looks like a register, data combination, 0 denoting a register address, | 210 | * This looks like a register, data combination, 0 denoting a register |
191 | * 1 denoting data. Addr 0x04 is used more than once and may be an enable. | 211 | * address, 1 denoting data. Addr 0x04 is used more than once is |
212 | * an enable. | ||
192 | */ | 213 | */ |
193 | const unsigned char initbuf[] = | 214 | const unsigned char initbuf[] = |
194 | { | 215 | { |
@@ -219,11 +240,51 @@ void lcd_init_device(void) | |||
219 | 0,0x04,1,0x01, | 240 | 0,0x04,1,0x01, |
220 | }; | 241 | }; |
221 | 242 | ||
222 | SPI_LCD_CS(true); | 243 | LCD_CTRL_clock(true); |
223 | SPI_Send_Bytes(initbuf, sizeof(initbuf)); | ||
224 | SPI_LCD_CS(false); | ||
225 | 244 | ||
226 | s3c_regclr(&CLKCON, 0x40000); /* disable SPI clock */ | 245 | LCD_SPI_start(); |
246 | |||
247 | LCD_SPI_send(initbuf, sizeof(initbuf)); | ||
248 | |||
249 | LCD_SPI_stop(); | ||
250 | } | ||
251 | |||
252 | /* LCD init */ | ||
253 | void lcd_init_device(void) | ||
254 | { | ||
255 | /* Set pins up */ | ||
256 | |||
257 | GPHUP &= 0x600; | ||
258 | |||
259 | GPECON |= 0x0A800000; | ||
260 | GPEUP |= 0x3800; | ||
261 | |||
262 | GPBUP |= 0x181; | ||
263 | |||
264 | s3c_regset(&CLKCON, 0x20); /* enable LCD clock */ | ||
265 | |||
266 | LCD_CTRL_setup(); | ||
267 | LCD_SPI_init(); | ||
268 | } | ||
269 | |||
270 | void lcd_enable(bool state) | ||
271 | { | ||
272 | if(state) | ||
273 | { | ||
274 | if(!lcd_on) | ||
275 | { | ||
276 | lcd_on = true; | ||
277 | lcd_update(); | ||
278 | LCD_SPI_powerup(); | ||
279 | } | ||
280 | } | ||
281 | else | ||
282 | { | ||
283 | if(lcd_on) { | ||
284 | lcd_on = false; | ||
285 | LCD_SPI_powerdown(); | ||
286 | } | ||
287 | } | ||
227 | } | 288 | } |
228 | 289 | ||
229 | /* Update a fraction of the display. */ | 290 | /* Update a fraction of the display. */ |
@@ -266,28 +327,6 @@ void lcd_update_rect(int x, int y, int width, int height) | |||
266 | } | 327 | } |
267 | } | 328 | } |
268 | 329 | ||
269 | void lcd_enable(bool state) | ||
270 | { | ||
271 | if(!lcd_poweroff) | ||
272 | return; | ||
273 | if(state) | ||
274 | { | ||
275 | if(!lcd_on) | ||
276 | { | ||
277 | lcd_on = true; | ||
278 | lcd_update(); | ||
279 | LCDCON1 |= 1; | ||
280 | } | ||
281 | } | ||
282 | else | ||
283 | { | ||
284 | if(lcd_on) { | ||
285 | lcd_on = false; | ||
286 | LCDCON1 &= ~1; | ||
287 | } | ||
288 | } | ||
289 | } | ||
290 | |||
291 | /* Update the display. | 330 | /* Update the display. |
292 | This must be called after all other LCD functions that change the display. */ | 331 | This must be called after all other LCD functions that change the display. */ |
293 | void lcd_update(void) | 332 | void lcd_update(void) |