summaryrefslogtreecommitdiff
path: root/firmware/target/coldfire/iriver/h300
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/coldfire/iriver/h300')
-rw-r--r--firmware/target/coldfire/iriver/h300/lcd-h300.c113
1 files changed, 78 insertions, 35 deletions
diff --git a/firmware/target/coldfire/iriver/h300/lcd-h300.c b/firmware/target/coldfire/iriver/h300/lcd-h300.c
index 867bc5ab74..36f340eab7 100644
--- a/firmware/target/coldfire/iriver/h300/lcd-h300.c
+++ b/firmware/target/coldfire/iriver/h300/lcd-h300.c
@@ -32,9 +32,14 @@
32#include "font.h" 32#include "font.h"
33#include "bidi.h" 33#include "bidi.h"
34 34
35static bool display_on = false; /* is the display turned on? */ 35static bool display_on = false; /* Is the display turned on? */
36static bool display_flipped = false; 36static bool display_flipped = false;
37static int xoffset = 0; /* needed for flip */ 37static int xoffset = 0; /* Needed for flip */
38static struct mutex lcd_mtx; /* The update functions use DMA and yield */
39
40unsigned long dma_addr IBSS_ATTR;
41unsigned int dma_len IBSS_ATTR;
42volatile int dma_count IBSS_ATTR;
38 43
39/* register defines */ 44/* register defines */
40#define R_START_OSC 0x00 45#define R_START_OSC 0x00
@@ -133,7 +138,11 @@ void lcd_set_flip(bool yesno)
133 xoffset = yesno ? 4 : 0; 138 xoffset = yesno ? 4 : 0;
134 139
135 if (display_on) 140 if (display_on)
141 {
142 mutex_lock(&lcd_mtx);
136 flip_lcd(yesno); 143 flip_lcd(yesno);
144 mutex_unlock(&lcd_mtx);
145 }
137} 146}
138 147
139static void _display_on(void) 148static void _display_on(void)
@@ -253,14 +262,22 @@ void lcd_init_device(void)
253 or_l(0x00004000, &GPIO1_OUT); 262 or_l(0x00004000, &GPIO1_OUT);
254 sleep(1); 263 sleep(1);
255 264
265 DAR3 = 0xf0000002; /* Configure DMA channel 3 */
266 DSR3 = 1;
267 DIVR3 = 57; /* DMA3 is mapped into vector 57 in system.c */
268 ICR9 = (6 << 2); /* Enable DMA3 interrupt at level 6, priority 0 */
269 and_l(~(1<<17), &IMR);
270
271 mutex_init(&lcd_mtx);
256 _display_on(); 272 _display_on();
257} 273}
258 274
259void lcd_enable(bool on) 275void lcd_enable(bool on)
260{ 276{
261 if(display_on!=on) 277 if (display_on != on)
262 { 278 {
263 if(on) 279 mutex_lock(&lcd_mtx);
280 if (on)
264 { 281 {
265 _display_on(); 282 _display_on();
266 lcd_activation_call_hook(); 283 lcd_activation_call_hook();
@@ -287,6 +304,7 @@ void lcd_enable(bool on)
287 304
288 display_on=false; 305 display_on=false;
289 } 306 }
307 mutex_unlock(&lcd_mtx);
290 } 308 }
291} 309}
292 310
@@ -322,6 +340,7 @@ void lcd_blit_yuv(unsigned char * const src[3],
322 if (!display_on) 340 if (!display_on)
323 return; 341 return;
324 342
343 mutex_lock(&lcd_mtx);
325 width &= ~1; /* stay on the safe side */ 344 width &= ~1; /* stay on the safe side */
326 height &= ~1; 345 height &= ~1;
327 346
@@ -353,14 +372,33 @@ void lcd_blit_yuv(unsigned char * const src[3],
353 vsrc += stride >> 1; 372 vsrc += stride >> 1;
354 } 373 }
355 while (ysrc < ysrc_max); 374 while (ysrc < ysrc_max);
375 mutex_unlock(&lcd_mtx);
356} 376}
357 377
378/* LCD DMA ISR */
379void DMA3(void) __attribute__ ((interrupt_handler, section(".icode")));
380void DMA3(void)
381{
382 DSR3 = 1;
383 if (--dma_count > 0)
384 {
385 dma_addr += LCD_WIDTH*sizeof(fb_data);
386 SAR3 = dma_addr;
387 BCR3 = dma_len;
388 DCR3 = DMA_INT | DMA_AA | DMA_BWC(1)
389 | DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE)
390 | DMA_DSIZE(DMA_SIZE_WORD) | DMA_START;
391 }
392}
393
358/* Update the display. 394/* Update the display.
359 This must be called after all other LCD functions that change the display. */ 395 This must be called after all other LCD functions that change the display. */
360void lcd_update(void) ICODE_ATTR;
361void lcd_update(void) 396void lcd_update(void)
362{ 397{
363 if(display_on){ 398 if (display_on)
399 {
400 mutex_lock(&lcd_mtx);
401
364 lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_VERT); 402 lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_VERT);
365 /* set start position window */ 403 /* set start position window */
366 lcd_write_reg(R_HORIZ_RAM_ADDR_POS, 175 << 8); 404 lcd_write_reg(R_HORIZ_RAM_ADDR_POS, 175 << 8);
@@ -369,57 +407,62 @@ void lcd_update(void)
369 407
370 lcd_begin_write_gram(); 408 lcd_begin_write_gram();
371 409
372 DAR3 = 0xf0000002; 410 dma_count = 1;
373 SAR3 = (unsigned long)lcd_framebuffer; 411 SAR3 = (unsigned long)lcd_framebuffer;
374 BCR3 = LCD_WIDTH*LCD_HEIGHT*2; 412 BCR3 = LCD_WIDTH*LCD_HEIGHT*sizeof(fb_data);
375 DCR3 = DMA_AA | DMA_BWC(1) 413 DCR3 = DMA_INT | DMA_AA | DMA_BWC(1)
376 | DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE) 414 | DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE)
377 | DMA_DSIZE(DMA_SIZE_WORD) | DMA_START; 415 | DMA_DSIZE(DMA_SIZE_WORD) | DMA_START;
378 416
379 while (!(DSR3 & 1)); 417 while (dma_count > 0)
380 DSR3 = 1; 418 yield();
419
420 mutex_unlock(&lcd_mtx);
381 } 421 }
382} 422}
383 423
384
385/* Update a fraction of the display. */ 424/* Update a fraction of the display. */
386void lcd_update_rect(int, int, int, int) ICODE_ATTR;
387void lcd_update_rect(int x, int y, int width, int height) 425void lcd_update_rect(int x, int y, int width, int height)
388{ 426{
389 unsigned long dma_addr; 427 if (display_on)
390 428 {
391 if(display_on) { 429 if (x + width > LCD_WIDTH)
392
393 if(x + width > LCD_WIDTH)
394 width = LCD_WIDTH - x; 430 width = LCD_WIDTH - x;
395 if(width <= 0) /* nothing to do */ 431 if (y + height > LCD_HEIGHT)
396 return;
397 if(y + height > LCD_HEIGHT)
398 height = LCD_HEIGHT - y; 432 height = LCD_HEIGHT - y;
399 433
434 if (width <= 0 || height <= 0) /* nothing to do */
435 return;
436
437 mutex_lock(&lcd_mtx);
438
400 lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_VERT); 439 lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_VERT);
401 /* set update window */ 440 /* set update window */
402 lcd_write_reg(R_HORIZ_RAM_ADDR_POS, 175 << 8); 441 lcd_write_reg(R_HORIZ_RAM_ADDR_POS, 175 << 8);
403 lcd_write_reg(R_VERT_RAM_ADDR_POS,((x+xoffset+width-1) << 8) | (x+xoffset)); 442 lcd_write_reg(R_VERT_RAM_ADDR_POS,((x+xoffset+width-1) << 8) | (x+xoffset));
404 lcd_write_reg(R_RAM_ADDR_SET, ((x+xoffset) << 8) | y); 443 lcd_write_reg(R_RAM_ADDR_SET, ((x+xoffset) << 8) | y);
444
405 lcd_begin_write_gram(); 445 lcd_begin_write_gram();
406 446
407 DAR3 = 0xf0000002; 447 if (width == LCD_WIDTH)
408 dma_addr = (unsigned long)&lcd_framebuffer[y][x]; 448 {
409 width *= 2; 449 dma_count = 1;
410 450 SAR3 = (unsigned long)lcd_framebuffer[y];
411 for (; height > 0; height--) 451 BCR3 = (LCD_WIDTH*sizeof(fb_data)) * height;
452 }
453 else
412 { 454 {
413 SAR3 = dma_addr; 455 dma_count = height;
414 BCR3 = width; 456 SAR3 = dma_addr = (unsigned long)&lcd_framebuffer[y][x];
415 DCR3 = DMA_AA | DMA_BWC(1) 457 BCR3 = dma_len = width * sizeof(fb_data);
416 | DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE) 458 }
417 | DMA_DSIZE(DMA_SIZE_WORD) | DMA_START; 459 DCR3 = DMA_INT | DMA_AA | DMA_BWC(1)
460 | DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE)
461 | DMA_DSIZE(DMA_SIZE_WORD) | DMA_START;
418 462
419 dma_addr += LCD_WIDTH*2; 463 while (dma_count > 0)
464 yield();
420 465
421 while (!(DSR3 & 1)); 466 mutex_unlock(&lcd_mtx);
422 DSR3 = 1;
423 }
424 } 467 }
425} 468}