diff options
Diffstat (limited to 'firmware/target/coldfire/iriver/h300')
-rw-r--r-- | firmware/target/coldfire/iriver/h300/lcd-h300.c | 113 |
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 | ||
35 | static bool display_on = false; /* is the display turned on? */ | 35 | static bool display_on = false; /* Is the display turned on? */ |
36 | static bool display_flipped = false; | 36 | static bool display_flipped = false; |
37 | static int xoffset = 0; /* needed for flip */ | 37 | static int xoffset = 0; /* Needed for flip */ |
38 | static struct mutex lcd_mtx; /* The update functions use DMA and yield */ | ||
39 | |||
40 | unsigned long dma_addr IBSS_ATTR; | ||
41 | unsigned int dma_len IBSS_ATTR; | ||
42 | volatile 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 | ||
139 | static void _display_on(void) | 148 | static 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 | ||
259 | void lcd_enable(bool on) | 275 | void 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 */ | ||
379 | void DMA3(void) __attribute__ ((interrupt_handler, section(".icode"))); | ||
380 | void 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. */ |
360 | void lcd_update(void) ICODE_ATTR; | ||
361 | void lcd_update(void) | 396 | void 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. */ |
386 | void lcd_update_rect(int, int, int, int) ICODE_ATTR; | ||
387 | void lcd_update_rect(int x, int y, int width, int height) | 425 | void 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 | } |