forked from len0rd/rockbox
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
This commit is contained in:
parent
0c1a304620
commit
15dfcd13ef
1 changed files with 43 additions and 13 deletions
|
@ -23,6 +23,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "lcd.h"
|
#include "lcd.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#define LCD_DATA_IN_GPIO GPIOB_INPUT_VAL
|
#define LCD_DATA_IN_GPIO GPIOB_INPUT_VAL
|
||||||
#define LCD_DATA_IN_PIN 6
|
#define LCD_DATA_IN_PIN 6
|
||||||
|
@ -48,6 +49,11 @@
|
||||||
#define LCD_REG_9 (*(volatile unsigned long *)(0xc2000024))
|
#define LCD_REG_9 (*(volatile unsigned long *)(0xc2000024))
|
||||||
#define LCD_FB_BASE_REG (*(volatile unsigned long *)(0xc2000028))
|
#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)
|
static inline void lcd_init_gpio(void)
|
||||||
{
|
{
|
||||||
GPIOB_ENABLE |= (1<<7);
|
GPIOB_ENABLE |= (1<<7);
|
||||||
|
@ -133,6 +139,10 @@ inline void lcd_init_device(void)
|
||||||
{
|
{
|
||||||
/* All this is magic worked out by MrH */
|
/* All this is magic worked out by MrH */
|
||||||
|
|
||||||
|
/* Stop any DMA which is in progress */
|
||||||
|
LCD_REG_6 &= ~1;
|
||||||
|
udelay(100000);
|
||||||
|
|
||||||
/* Init GPIO ports */
|
/* Init GPIO ports */
|
||||||
lcd_init_gpio();
|
lcd_init_gpio();
|
||||||
/* Controller init */
|
/* Controller init */
|
||||||
|
@ -179,7 +189,7 @@ inline void lcd_init_device(void)
|
||||||
LCD_REG_6 |= (1 << 4);
|
LCD_REG_6 |= (1 << 4);
|
||||||
|
|
||||||
LCD_REG_5 &= ~(1 << 7);
|
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);
|
udelay(100000);
|
||||||
|
|
||||||
|
@ -247,20 +257,40 @@ inline void lcd_init_device(void)
|
||||||
lcd_send_msg(0x70, 34);
|
lcd_send_msg(0x70, 34);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void lcd_update(void)
|
|
||||||
{
|
|
||||||
cache_flush();
|
|
||||||
if(!(LCD_REG_6 & 1))
|
|
||||||
LCD_REG_6 |= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void lcd_update_rect(int x, int y, int width, int height)
|
inline void lcd_update_rect(int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
(void) x;
|
(void)x;
|
||||||
(void) y;
|
(void)width;
|
||||||
(void) width;
|
/* Turn off DMA and wait for the transfer to complete */
|
||||||
(void) height;
|
/* TODO: Work out the proper delay */
|
||||||
lcd_update();
|
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();
|
||||||
|
|
||||||
|
/* Restart DMA */
|
||||||
|
LCD_REG_6 |= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void lcd_update(void)
|
||||||
|
{
|
||||||
|
/* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue