summaryrefslogtreecommitdiff
path: root/firmware/target
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target')
-rw-r--r--firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c310
1 files changed, 197 insertions, 113 deletions
diff --git a/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c b/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c
index c9dd69d47b..d10396cfd4 100644
--- a/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c
+++ b/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c
@@ -31,22 +31,68 @@
31 31
32/* The controller is unknown, but some registers appear to be the same as the 32/* The controller is unknown, but some registers appear to be the same as the
33 HD66789R */ 33 HD66789R */
34static bool display_on = false; /* is the display turned on? */
34 35
36/* register defines */
37#define R_START_OSC 0x00
38#define R_DRV_OUTPUT_CONTROL 0x01
39#define R_DRV_WAVEFORM_CONTROL 0x02
35#define R_ENTRY_MODE 0x03 40#define R_ENTRY_MODE 0x03
36#define R_RAM_ADDR_SET 0x21 41#define R_COMPARE_REG1 0x04
37#define R_WRITE_DATA_2_GRAM 0x22 42#define R_COMPARE_REG2 0x05
38 43
39#define R_ENTRY_MODE_HORZ 0x7030 44#define R_DISP_CONTROL1 0x07
45#define R_DISP_CONTROL2 0x08
46#define R_DISP_CONTROL3 0x09
47
48#define R_FRAME_CYCLE_CONTROL 0x0b
49#define R_EXT_DISP_IF_CONTROL 0x0c
50
51#define R_POWER_CONTROL1 0x10
52#define R_POWER_CONTROL2 0x11
53#define R_POWER_CONTROL3 0x12
54#define R_POWER_CONTROL4 0x13
55
56#define R_RAM_ADDR_SET 0x21
57#define R_WRITE_DATA_2_GRAM 0x22
58
59#define R_GAMMA_FINE_ADJ_POS1 0x30
60#define R_GAMMA_FINE_ADJ_POS2 0x31
61#define R_GAMMA_FINE_ADJ_POS3 0x32
62#define R_GAMMA_GRAD_ADJ_POS 0x33
63
64#define R_GAMMA_FINE_ADJ_NEG1 0x34
65#define R_GAMMA_FINE_ADJ_NEG2 0x35
66#define R_GAMMA_FINE_ADJ_NEG3 0x36
67#define R_GAMMA_GRAD_ADJ_NEG 0x37
68
69#define R_GAMMA_AMP_ADJ_RES_POS 0x38
70#define R_GAMMA_AMP_AVG_ADJ_RES_NEG 0x39
71
72#define R_GATE_SCAN_POS 0x40
73#define R_VERT_SCROLL_CONTROL 0x41
74#define R_1ST_SCR_DRV_POS 0x42
75#define R_2ND_SCR_DRV_POS 0x43
76#define R_HORIZ_RAM_ADDR_POS 0x44
77#define R_VERT_RAM_ADDR_POS 0x45
78
79/* Flip Flag */
80#define R_ENTRY_MODE_HORZ_NORMAL 0x7030
81#define R_ENTRY_MODE_HORZ_FLIPPED 0x7000
82static unsigned short r_entry_mode = R_ENTRY_MODE_HORZ_NORMAL;
40#define R_ENTRY_MODE_VERT 0x7038 83#define R_ENTRY_MODE_VERT 0x7038
84#define R_ENTRY_MODE_SOLID_VERT 0x1038
85/* FIXME */
86#define R_ENTRY_MODE_VIDEO_NORMAL 0x7038
87#define R_ENTRY_MODE_VIDEO_FLIPPED 0x7018
41 88
42static unsigned lcd_yuv_options = 0; 89/* Reverse Flag */
43static bool display_on = false; /* is the display turned on? */ 90#define R_DISP_CONTROL_NORMAL 0x0004
44static bool display_flipped = false; 91#define R_DISP_CONTROL_REV 0x0000
45static int xoffset = 20; /* needed for flip */ 92static unsigned short r_disp_control_rev = R_DISP_CONTROL_NORMAL;
46/* we need to write a red pixel for correct button reads 93
47 * (see lcd_button_support()),but that must not happen while the lcd is updating 94static const int xoffset = 20;
48 * so block lcd_button_support the during updates */ 95static volatile bool lcd_busy = false;
49static volatile int lcd_busy = false;
50 96
51static inline void lcd_delay(int x) 97static inline void lcd_delay(int x)
52{ 98{
@@ -54,7 +100,7 @@ static inline void lcd_delay(int x)
54 asm volatile ("nop\n"); 100 asm volatile ("nop\n");
55 } while (x--); 101 } while (x--);
56} 102}
57 103
58static void as3525_dbop_init(void) 104static void as3525_dbop_init(void)
59{ 105{
60 CGU_DBOP = (1<<3) | AS3525_DBOP_DIV; 106 CGU_DBOP = (1<<3) | AS3525_DBOP_DIV;
@@ -69,6 +115,7 @@ static void as3525_dbop_init(void)
69 GPIOC_AFSEL = 0xff; 115 GPIOC_AFSEL = 0xff;
70 116
71 DBOP_TIMPOL_23 = 0x6000e; 117 DBOP_TIMPOL_23 = 0x6000e;
118
72 /* short count: 16|enable write|output data width: 16|read strobe line */ 119 /* short count: 16|enable write|output data width: 16|read strobe line */
73 DBOP_CTRL = (1<<18|1<<16|1<<12|1<<3); 120 DBOP_CTRL = (1<<18|1<<16|1<<12|1<<3);
74 DBOP_TIMPOL_01 = 0x6e167; 121 DBOP_TIMPOL_01 = 0x6e167;
@@ -94,7 +141,6 @@ static void lcd_write_cmd(int cmd)
94 /* Wait for fifo to empty */ 141 /* Wait for fifo to empty */
95 while ((DBOP_STAT & (1<<10)) == 0); 142 while ((DBOP_STAT & (1<<10)) == 0);
96 143
97 /* This loop is unique to the Fuze */
98 lcd_delay(4); 144 lcd_delay(4);
99 145
100 DBOP_TIMPOL_23 = 0xa167e06f; 146 DBOP_TIMPOL_23 = 0xa167e06f;
@@ -105,12 +151,12 @@ void lcd_write_data(const fb_data* p_bytes, int count)
105 const long *data; 151 const long *data;
106 if ((int)p_bytes & 0x3) 152 if ((int)p_bytes & 0x3)
107 { /* need to do a single 16bit write beforehand if the address is 153 { /* need to do a single 16bit write beforehand if the address is
108 * not word aligned*/ 154 * not word aligned */
109 lcd_write_value16(*p_bytes); 155 lcd_write_value16(*p_bytes);
110 count--;p_bytes++; 156 count--;p_bytes++;
111 } 157 }
112 /* from here, 32bit transfers are save */ 158 /* from here, 32bit transfers are save
113 /* set it to transfer 4*(outputwidth) units at a time, 159 * set it to transfer 4*(outputwidth) units at a time,
114 * if bit 12 is set it only does 2 halfwords though */ 160 * if bit 12 is set it only does 2 halfwords though */
115 DBOP_CTRL |= (1<<13|1<<14); 161 DBOP_CTRL |= (1<<13|1<<14);
116 lcd_delay(10); 162 lcd_delay(10);
@@ -129,92 +175,128 @@ void lcd_write_data(const fb_data* p_bytes, int count)
129 /* due to the 32bit alignment requirement or uneven count, 175 /* due to the 32bit alignment requirement or uneven count,
130 * we possibly need to do a 16bit transfer at the end also */ 176 * we possibly need to do a 16bit transfer at the end also */
131 if (count > 0) 177 if (count > 0)
132 lcd_write_value16(*(unsigned short*)data); 178 lcd_write_value16(*(fb_data*)data);
133} 179}
134 180
135static void lcd_write_reg(int reg, int value) 181static void lcd_write_reg(int reg, int value)
136{ 182{
137 unsigned short data = value; 183 fb_data data = value;
138 184
139 lcd_write_cmd(reg); 185 lcd_write_cmd(reg);
140 lcd_write_value16(data); 186 lcd_write_value16(data);
141} 187}
142 188
143/* turn the display upside down (call lcd_update() afterwards) */ 189/*** hardware configuration ***/
190
191void lcd_set_contrast(int val)
192{
193 (void)val;
194}
195
196void lcd_set_invert_display(bool yesno)
197{
198 r_disp_control_rev = yesno ? R_DISP_CONTROL_REV :
199 R_DISP_CONTROL_NORMAL;
200
201 if (display_on)
202 {
203 lcd_write_reg(R_DISP_CONTROL1, 0x0013 | r_disp_control_rev);
204 }
205
206}
207
208#ifdef HAVE_LCD_FLIP
209static bool display_flipped = false;
210
211/* turn the display upside down */
144void lcd_set_flip(bool yesno) 212void lcd_set_flip(bool yesno)
145{ 213{
146 display_flipped = yesno; 214 display_flipped = yesno;
147 xoffset = yesno ? 0 : 20; /* TODO: Implement flipped mode */
148 215
149 /* TODO */ 216 r_entry_mode = yesno ? R_ENTRY_MODE_HORZ_FLIPPED :
217 R_ENTRY_MODE_HORZ_NORMAL;
150} 218}
151 219#endif
152 220
153static void _display_on(void) 221static void _display_on(void)
154{ 222{
155 /* Initialise in the same way as the original firmare */ 223 /* Initialise in the same way as the original firmare */
156 224
157 lcd_write_reg(0x07, 0); 225 lcd_write_reg(R_DISP_CONTROL1, 0);
158 lcd_write_reg(0x13, 0); 226 lcd_write_reg(R_POWER_CONTROL4, 0);
159 227
160 lcd_write_reg(0x11, 0x3704); 228 lcd_write_reg(R_POWER_CONTROL2, 0x3704);
161 lcd_write_reg(0x14, 0x1a1b); 229 lcd_write_reg(0x14, 0x1a1b);
162 lcd_write_reg(0x10, 0x3860); 230 lcd_write_reg(R_POWER_CONTROL1, 0x3860);
163 lcd_write_reg(0x13, 0x40); 231 lcd_write_reg(R_POWER_CONTROL4, 0x40);
164 232
165 lcd_write_reg(0x13, 0x60); 233 lcd_write_reg(R_POWER_CONTROL4, 0x60);
166 234
167 lcd_write_reg(0x13, 0x70); 235 lcd_write_reg(R_POWER_CONTROL4, 0x70);
168 lcd_write_reg(0x01, 277); 236 lcd_write_reg(R_DRV_OUTPUT_CONTROL, 277);
169 lcd_write_reg(0x02, (7<<8)); 237 lcd_write_reg(R_DRV_WAVEFORM_CONTROL, (7<<8));
170 lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_HORZ); 238 lcd_write_reg(R_ENTRY_MODE, r_entry_mode);
171 lcd_write_reg(0x08, 0x01); 239 lcd_write_reg(R_DISP_CONTROL2, 0x01);
172 lcd_write_reg(0x0b, (1<<10)); 240 lcd_write_reg(R_FRAME_CYCLE_CONTROL, (1<<10));
173 lcd_write_reg(0x0c, 0); 241 lcd_write_reg(R_EXT_DISP_IF_CONTROL, 0);
174 242
175 lcd_write_reg(0x30, 0x40); 243 lcd_write_reg(R_GAMMA_FINE_ADJ_POS1, 0x40);
176 lcd_write_reg(0x31, 0x0687); 244 lcd_write_reg(R_GAMMA_FINE_ADJ_POS2, 0x0687);
177 lcd_write_reg(0x32, 0x0306); 245 lcd_write_reg(R_GAMMA_FINE_ADJ_POS3, 0x0306);
178 lcd_write_reg(0x33, 0x104); 246 lcd_write_reg(R_GAMMA_GRAD_ADJ_POS, 0x104);
179 lcd_write_reg(0x34, 0x0585); 247 lcd_write_reg(R_GAMMA_FINE_ADJ_NEG1, 0x0585);
180 lcd_write_reg(0x35, 255+66); 248 lcd_write_reg(R_GAMMA_FINE_ADJ_NEG2, 255+66);
181 lcd_write_reg(0x36, 0x0687+128); 249 lcd_write_reg(R_GAMMA_FINE_ADJ_NEG3, 0x0687+128);
182 lcd_write_reg(0x37, 259); 250 lcd_write_reg(R_GAMMA_GRAD_ADJ_NEG, 259);
183 lcd_write_reg(0x38, 0); 251 lcd_write_reg(R_GAMMA_AMP_ADJ_RES_POS, 0);
184 lcd_write_reg(0x39, 0); 252 lcd_write_reg(R_GAMMA_AMP_AVG_ADJ_RES_NEG, 0);
185 253
186 lcd_write_reg(0x42, (LCD_WIDTH - 1)); 254 lcd_write_reg(R_1ST_SCR_DRV_POS, (LCD_WIDTH - 1));
187 lcd_write_reg(0x43, 0); 255 lcd_write_reg(R_2ND_SCR_DRV_POS, 0);
188 lcd_write_reg(0x44, (LCD_WIDTH - 1)); 256 lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (LCD_WIDTH - 1));
189 lcd_write_reg(0x45, 0); 257 lcd_write_reg(R_VERT_RAM_ADDR_POS, 0);
190 lcd_write_reg(0x46, (((LCD_WIDTH - 1) + xoffset) << 8) | xoffset); 258 lcd_write_reg(0x46, (((LCD_WIDTH - 1) + xoffset) << 8) | xoffset);
191 lcd_write_reg(0x47, (LCD_HEIGHT - 1)); 259 lcd_write_reg(0x47, (LCD_HEIGHT - 1));
192 lcd_write_reg(0x48, 0x0); 260 lcd_write_reg(0x48, 0x0);
193 261
194 lcd_write_reg(0x07, 0x11); 262 lcd_write_reg(R_DISP_CONTROL1, 0x11);
195 lcd_write_reg(0x07, 0x17); 263 lcd_write_reg(R_DISP_CONTROL1, 0x13 | r_disp_control_rev);
196 264
197 display_on = true; /* must be done before calling lcd_update() */ 265 display_on = true; /* must be done before calling lcd_update() */
198 lcd_update(); 266 lcd_update();
199} 267}
200 268
269void lcd_init_device(void)
270{
271 as3525_dbop_init();
272
273 GPIOA_DIR |= (1<<5|1<<4|1<<3);
274 GPIOA_PIN(5) = 0;
275 GPIOA_PIN(3) = (1<<3);
276 GPIOA_PIN(4) = 0;
277 GPIOA_PIN(5) = (1<<5);
278
279 _display_on();
280}
281
201#if defined(HAVE_LCD_ENABLE) 282#if defined(HAVE_LCD_ENABLE)
202void lcd_enable(bool on) 283void lcd_enable(bool on)
203{ 284{
204 if (display_on == on) 285 if (display_on == on)
205 return; /* nothing to do */ 286 return;
287
206 if(on) 288 if(on)
207 { 289 {
208 lcd_write_reg(0, 1); 290 lcd_write_reg(R_START_OSC, 1);
209 lcd_write_reg(0x10, 0); 291 lcd_write_reg(R_POWER_CONTROL1, 0);
210 lcd_write_reg(0x11, 0x3704); 292 lcd_write_reg(R_POWER_CONTROL2, 0x3704);
211 lcd_write_reg(0x14, 0x1a1b); 293 lcd_write_reg(0x14, 0x1a1b);
212 lcd_write_reg(0x10, 0x3860); 294 lcd_write_reg(R_POWER_CONTROL1, 0x3860);
213 lcd_write_reg(0x13, 0x40); 295 lcd_write_reg(R_POWER_CONTROL4, 0x40);
214 lcd_write_reg(0x13, 0x60); 296 lcd_write_reg(R_POWER_CONTROL4, 0x60);
215 lcd_write_reg(0x13, 112); 297 lcd_write_reg(R_POWER_CONTROL4, 112);
216 lcd_write_reg(0x07, 0x11); 298 lcd_write_reg(R_DISP_CONTROL1, 0x11);
217 lcd_write_reg(0x07, 0x17); 299 lcd_write_reg(R_DISP_CONTROL1, 0x13 | r_disp_control_rev);
218 display_on = true; 300 display_on = true;
219 lcd_update(); /* Resync display */ 301 lcd_update(); /* Resync display */
220 send_event(LCD_EVENT_ACTIVATION, NULL); 302 send_event(LCD_EVENT_ACTIVATION, NULL);
@@ -223,9 +305,9 @@ void lcd_enable(bool on)
223 } 305 }
224 else 306 else
225 { 307 {
226 lcd_write_reg(0x07, 0x22); 308 lcd_write_reg(R_DISP_CONTROL1, 0x22);
227 lcd_write_reg(0x07, 0); 309 lcd_write_reg(R_DISP_CONTROL1, 0);
228 lcd_write_reg(0x10, 1); 310 lcd_write_reg(R_POWER_CONTROL1, 1);
229 display_on = false; 311 display_on = false;
230 } 312 }
231} 313}
@@ -240,23 +322,28 @@ bool lcd_active(void)
240 322
241/*** update functions ***/ 323/*** update functions ***/
242 324
325/* FIXME : find the datasheet for this RENESAS controller so we identify the
326 * registers used in windowing code (not present in HD66789R) */
327
243/* Set horizontal window addresses */ 328/* Set horizontal window addresses */
244static void lcd_window_x(int xmin, int xmax) 329static void lcd_window_x(int xmin, int xmax)
245{ 330{
246 xmin += xoffset; 331 xmin += xoffset;
247 xmax += xoffset; 332 xmax += xoffset;
248 lcd_write_reg(0x46, (xmax << 8) | xmin); 333 lcd_write_reg(R_HORIZ_RAM_ADDR_POS + 2, (xmax << 8) | xmin);
249 lcd_write_reg(0x20, xmin); 334 lcd_write_reg(R_RAM_ADDR_SET - 1, xmin);
250} 335}
251 336
252/* Set vertical window addresses */ 337/* Set vertical window addresses */
253static void lcd_window_y(int ymin, int ymax) 338static void lcd_window_y(int ymin, int ymax)
254{ 339{
255 lcd_write_reg(0x47, ymax); 340 lcd_write_reg(R_VERT_RAM_ADDR_POS + 2, ymax);
256 lcd_write_reg(0x48, ymin); 341 lcd_write_reg(R_VERT_RAM_ADDR_POS + 3, ymin);
257 lcd_write_reg(0x21, ymin); 342 lcd_write_reg(R_RAM_ADDR_SET, ymin);
258} 343}
259 344
345static unsigned lcd_yuv_options = 0;
346
260void lcd_yuv_set_options(unsigned options) 347void lcd_yuv_set_options(unsigned options)
261{ 348{
262 lcd_yuv_options = options; 349 lcd_yuv_options = options;
@@ -267,11 +354,15 @@ extern void lcd_write_yuv420_lines(unsigned char const * const src[3],
267 int width, 354 int width,
268 int stride); 355 int stride);
269extern void lcd_write_yuv420_lines_odither(unsigned char const * const src[3], 356extern void lcd_write_yuv420_lines_odither(unsigned char const * const src[3],
270 int width, 357 int width,
271 int stride, 358 int stride,
272 int x_screen, /* To align dither */ 359 int x_screen, /* To align dither pattern */
273 int y_screen); /* pattern */ 360 int y_screen);
274/* Performance function to blit a YUV bitmap directly to the LCD */ 361
362/* Performance function to blit a YUV bitmap directly to the LCD
363 * src_x, src_y, width and height should be even
364 * x, y, width and height have to be within LCD bounds
365 */
275void lcd_blit_yuv(unsigned char * const src[3], 366void lcd_blit_yuv(unsigned char * const src[3],
276 int src_x, int src_y, int stride, 367 int src_x, int src_y, int stride,
277 int x, int y, int width, int height) 368 int x, int y, int width, int height)
@@ -279,10 +370,6 @@ void lcd_blit_yuv(unsigned char * const src[3],
279 unsigned char const * yuv_src[3]; 370 unsigned char const * yuv_src[3];
280 off_t z; 371 off_t z;
281 372
282 lcd_busy = true;
283
284 lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_VERT);
285
286 /* Sorry, but width and height must be >= 2 or else */ 373 /* Sorry, but width and height must be >= 2 or else */
287 width &= ~1; 374 width &= ~1;
288 height >>= 1; 375 height >>= 1;
@@ -292,6 +379,16 @@ void lcd_blit_yuv(unsigned char * const src[3],
292 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1); 379 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
293 yuv_src[2] = src[2] + (yuv_src[1] - src[1]); 380 yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
294 381
382 lcd_busy = true;
383
384#ifdef HAVE_LCD_FLIP
385 lcd_write_reg(R_ENTRY_MODE,
386 display_flipped ? R_ENTRY_MODE_VIDEO_FLIPPED : R_ENTRY_MODE_VIDEO_NORMAL
387 );
388#else
389 lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_VIDEO_NORMAL);
390#endif
391
295 lcd_window_x(x, x + width - 1); 392 lcd_window_x(x, x + width - 1);
296 393
297 if (lcd_yuv_options & LCD_YUV_DITHER) 394 if (lcd_yuv_options & LCD_YUV_DITHER)
@@ -299,7 +396,7 @@ void lcd_blit_yuv(unsigned char * const src[3],
299 do 396 do
300 { 397 {
301 lcd_window_y(y, y + 1); 398 lcd_window_y(y, y + 1);
302 /* Start write to GRAM */ 399
303 lcd_write_cmd(R_WRITE_DATA_2_GRAM); 400 lcd_write_cmd(R_WRITE_DATA_2_GRAM);
304 401
305 lcd_write_yuv420_lines_odither(yuv_src, width, stride, x, y); 402 lcd_write_yuv420_lines_odither(yuv_src, width, stride, x, y);
@@ -308,14 +405,14 @@ void lcd_blit_yuv(unsigned char * const src[3],
308 yuv_src[2] += stride >> 1; 405 yuv_src[2] += stride >> 1;
309 y += 2; 406 y += 2;
310 } 407 }
311 while (--height > 0); 408 while (--height > 0);
312 } 409 }
313 else 410 else
314 { 411 {
315 do 412 do
316 { 413 {
317 lcd_window_y(y, y + 1); 414 lcd_window_y(y, y + 1);
318 /* Start write to GRAM */ 415
319 lcd_write_cmd(R_WRITE_DATA_2_GRAM); 416 lcd_write_cmd(R_WRITE_DATA_2_GRAM);
320 417
321 lcd_write_yuv420_lines(yuv_src, width, stride); 418 lcd_write_yuv420_lines(yuv_src, width, stride);
@@ -324,25 +421,12 @@ void lcd_blit_yuv(unsigned char * const src[3],
324 yuv_src[2] += stride >> 1; 421 yuv_src[2] += stride >> 1;
325 y += 2; 422 y += 2;
326 } 423 }
327 while (--height > 0); 424 while (--height > 0);
328 } 425 }
329 426
330 lcd_busy = false; 427 lcd_busy = false;
331} 428}
332 429
333void lcd_init_device()
334{
335 as3525_dbop_init();
336
337 GPIOA_DIR |= (1<<5|1<<4|1<<3);
338 GPIOA_PIN(5) = 0;
339 GPIOA_PIN(3) = (1<<3);
340 GPIOA_PIN(4) = 0;
341 GPIOA_PIN(5) = (1<<5);
342
343 _display_on();
344}
345
346/* Update the display. 430/* Update the display.
347 This must be called after all other LCD functions that change the display. */ 431 This must be called after all other LCD functions that change the display. */
348void lcd_update(void) 432void lcd_update(void)
@@ -352,29 +436,27 @@ void lcd_update(void)
352 436
353 lcd_busy = true; 437 lcd_busy = true;
354 438
355 lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_HORZ); 439 lcd_write_reg(R_ENTRY_MODE, r_entry_mode);
356 440
357 lcd_window_x(0, LCD_WIDTH - 1); 441 lcd_window_x(0, LCD_WIDTH - 1);
358 lcd_window_y(0, LCD_HEIGHT - 1); 442 lcd_window_y(0, LCD_HEIGHT - 1);
359 443
360 /* Start write to GRAM */
361 lcd_write_cmd(R_WRITE_DATA_2_GRAM); 444 lcd_write_cmd(R_WRITE_DATA_2_GRAM);
362 445
363 /* Write data */ 446 lcd_write_data((fb_data*)lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT);
364 lcd_write_data((unsigned short *)lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT); 447
365 lcd_busy = false; 448 lcd_busy = false;
366} 449}
367 450
368/* Update a fraction of the display. */ 451/* Update a fraction of the display. */
369void lcd_update_rect(int x, int y, int width, int height) 452void lcd_update_rect(int x, int y, int width, int height)
370{ 453{
371 int xmax, ymax;
372 const fb_data *ptr; 454 const fb_data *ptr;
455 int xmax, ymax;
373 456
374 if (!display_on) 457 if (!display_on)
375 return; 458 return;
376 459
377
378 xmax = x + width; 460 xmax = x + width;
379 if (xmax >= LCD_WIDTH) 461 if (xmax >= LCD_WIDTH)
380 xmax = LCD_WIDTH - 1; /* Clip right */ 462 xmax = LCD_WIDTH - 1; /* Clip right */
@@ -395,12 +477,11 @@ void lcd_update_rect(int x, int y, int width, int height)
395 477
396 lcd_busy = true; 478 lcd_busy = true;
397 479
398 lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_HORZ); 480 lcd_write_reg(R_ENTRY_MODE, r_entry_mode);
399 481
400 lcd_window_x(x, xmax); 482 lcd_window_x(x, xmax);
401 lcd_window_y(y, ymax); 483 lcd_window_y(y, ymax);
402 484
403 /* Start write to GRAM */
404 lcd_write_cmd(R_WRITE_DATA_2_GRAM); 485 lcd_write_cmd(R_WRITE_DATA_2_GRAM);
405 486
406 ptr = &lcd_framebuffer[y][x]; 487 ptr = &lcd_framebuffer[y][x];
@@ -412,23 +493,26 @@ void lcd_update_rect(int x, int y, int width, int height)
412 ptr += LCD_WIDTH; 493 ptr += LCD_WIDTH;
413 } 494 }
414 while (--height >= 0); 495 while (--height >= 0);
496
415 lcd_busy = false; 497 lcd_busy = false;
416} 498}
417 499
418/* writes one read pixel outside the visible area, needed for correct dbop reads */ 500/* writes one red pixel outside the visible area, needed for correct
501 * dbop reads */
419bool lcd_button_support(void) 502bool lcd_button_support(void)
420{ 503{
421 fb_data data = 0xf<<12;
422 if (lcd_busy) 504 if (lcd_busy)
423 return false; 505 return false;
424 lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_HORZ);
425 /* Set start position and window */
426 506
507 lcd_write_reg(R_ENTRY_MODE, r_entry_mode);
508
509 /* Set start position and window */
427 lcd_window_x(-1, 0); 510 lcd_window_x(-1, 0);
428 lcd_window_y(-1, 0); 511 lcd_window_y(-1, 0);
512
429 lcd_write_cmd(R_WRITE_DATA_2_GRAM); 513 lcd_write_cmd(R_WRITE_DATA_2_GRAM);
430 514
431 lcd_write_value16(data); 515 lcd_write_value16(0xf<<12);
432 516
433 return true; 517 return true;
434} 518}