summaryrefslogtreecommitdiff
path: root/firmware/target/arm/sandisk
diff options
context:
space:
mode:
authorDaniel Ankers <dan@weirdo.org.uk>2007-03-20 10:52:02 +0000
committerDaniel Ankers <dan@weirdo.org.uk>2007-03-20 10:52:02 +0000
commit15dfcd13ef809c468ac44328b23715224c0cd2af (patch)
tree8f8beb140db20240b3fd8e324cfe51164f7b4308 /firmware/target/arm/sandisk
parent0c1a304620432e16f897e3ff36d28b76f0eb22b8 (diff)
Improved LCD driver for Sansa. Uses double-buffering to cure the flickering. Stops DMA during device initialization, which should stop the occasional hangs - based on FS#6859 by Antonius Hellmann
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12848 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/sandisk')
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/lcd-e200.c50
1 files changed, 40 insertions, 10 deletions
diff --git a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c
index e34ebd7c5a..d62688996e 100644
--- a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c
+++ b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c
@@ -23,6 +23,7 @@
#include "config.h"
#include "lcd.h"
#include "system.h"
+#include <string.h>
#define LCD_DATA_IN_GPIO GPIOB_INPUT_VAL
#define LCD_DATA_IN_PIN 6
@@ -48,6 +49,11 @@
#define LCD_REG_9 (*(volatile unsigned long *)(0xc2000024))
#define LCD_FB_BASE_REG (*(volatile unsigned long *)(0xc2000028))
+/* We don't know how to receive a DMA finished signal from the LCD controller
+ * To avoid problems with flickering, we double-buffer the framebuffer and turn
+ * off DMA while updates are taking place */
+fb_data lcd_driver_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH];
+
static inline void lcd_init_gpio(void)
{
GPIOB_ENABLE |= (1<<7);
@@ -133,6 +139,10 @@ inline void lcd_init_device(void)
{
/* All this is magic worked out by MrH */
+/* Stop any DMA which is in progress */
+ LCD_REG_6 &= ~1;
+ udelay(100000);
+
/* Init GPIO ports */
lcd_init_gpio();
/* Controller init */
@@ -179,7 +189,7 @@ inline void lcd_init_device(void)
LCD_REG_6 |= (1 << 4);
LCD_REG_5 &= ~(1 << 7);
- LCD_FB_BASE_REG = phys_fb_address((unsigned long)lcd_framebuffer);
+ LCD_FB_BASE_REG = phys_fb_address((unsigned long)lcd_driver_framebuffer);
udelay(100000);
@@ -247,20 +257,40 @@ inline void lcd_init_device(void)
lcd_send_msg(0x70, 34);
}
-inline void lcd_update(void)
+inline void lcd_update_rect(int x, int y, int width, int height)
{
+ (void)x;
+ (void)width;
+ /* Turn off DMA and wait for the transfer to complete */
+ /* TODO: Work out the proper delay */
+ LCD_REG_6 &= ~1;
+ udelay(1000);
+
+ /* Copy the Rockbox framebuffer to the second framebuffer */
+ /* TODO: Move the second framebuffer into uncached SDRAM */
+ memcpy(((char*)&lcd_driver_framebuffer)+(y * sizeof(fb_data) * LCD_WIDTH),
+ ((char *)&lcd_framebuffer)+(y * sizeof(fb_data) * LCD_WIDTH),
+ ((height * sizeof(fb_data) * LCD_WIDTH)));
cache_flush();
- if(!(LCD_REG_6 & 1))
- LCD_REG_6 |= 1;
+
+ /* Restart DMA */
+ LCD_REG_6 |= 1;
}
-inline void lcd_update_rect(int x, int y, int width, int height)
+inline void lcd_update(void)
{
- (void) x;
- (void) y;
- (void) width;
- (void) height;
- lcd_update();
+ /* TODO: It may be faster to swap the addresses of lcd_driver_framebuffer
+ * and lcd_framebuffer */
+ /* Turn off DMA and wait for the transfer to complete */
+ LCD_REG_6 &= ~1;
+ udelay(1000);
+
+ /* Copy the Rockbox framebuffer to the second framebuffer */
+ memcpy(lcd_driver_framebuffer, lcd_framebuffer, sizeof(fb_data) * LCD_WIDTH * LCD_HEIGHT);
+ cache_flush();
+
+ /* Restart DMA */
+ LCD_REG_6 |= 1;
}