summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Kurbjun <kkurbjun@gmail.com>2008-05-14 00:26:28 +0000
committerKarl Kurbjun <kkurbjun@gmail.com>2008-05-14 00:26:28 +0000
commit6e322c878695e9b6dbf5620feda76315a523cc43 (patch)
treefa752c8f5419c4c27dabcc53dedba2b0ad4f9f97
parentf7e0e6bb1cfc079cfbf18ce3224442be26ba46f2 (diff)
downloadrockbox-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.c249
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
69void SPI_LCD_CS(bool select) 69void 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
91void 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
82void reset_LCD(bool reset) 120void reset_LCD(bool reset)
@@ -89,7 +127,7 @@ void reset_LCD(bool reset)
89 GPBDAT&=~0x80; 127 GPBDAT&=~0x80;
90} 128}
91 129
92void SPI_Send_Bytes(const unsigned char *array, int count) 130void 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
101void Setup_LCD_SPI(void) 139void 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
109void 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 */ 152void 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 */ 163void LCD_SPI_stop(void)
132void 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; 171void 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(); 188void 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 204void 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 */
253void 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
270void 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
269void 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. */
293void lcd_update(void) 332void lcd_update(void)