summaryrefslogtreecommitdiffstats
path: root/firmware/target/arm/s5l8700/meizu-m6sp/lcd-m6sp.c
diff options
context:
space:
mode:
authorBertrik Sikken <bertrik@sikken.nl>2009-10-25 11:31:13 +0000
committerBertrik Sikken <bertrik@sikken.nl>2009-10-25 11:31:13 +0000
commit52ca187f68ff3d74f604b4e12048aacaed451a24 (patch)
treebb1478eb365e695e4efbc9fd07adf9c64579cffd /firmware/target/arm/s5l8700/meizu-m6sp/lcd-m6sp.c
parentf3944cb694b46052975f0a1f1ec9b0aebe047679 (diff)
downloadrockbox-52ca187f68ff3d74f604b4e12048aacaed451a24.tar.gz
rockbox-52ca187f68ff3d74f604b4e12048aacaed451a24.tar.bz2
rockbox-52ca187f68ff3d74f604b4e12048aacaed451a24.zip
Meizu M6 SP: update lcd driver, it is now possible to display a rockbox logo (with some limitations, see comments in lcd-m6sp.c)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23345 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/s5l8700/meizu-m6sp/lcd-m6sp.c')
-rw-r--r--firmware/target/arm/s5l8700/meizu-m6sp/lcd-m6sp.c157
1 files changed, 90 insertions, 67 deletions
diff --git a/firmware/target/arm/s5l8700/meizu-m6sp/lcd-m6sp.c b/firmware/target/arm/s5l8700/meizu-m6sp/lcd-m6sp.c
index b6330406f2..9a24480bfa 100644
--- a/firmware/target/arm/s5l8700/meizu-m6sp/lcd-m6sp.c
+++ b/firmware/target/arm/s5l8700/meizu-m6sp/lcd-m6sp.c
@@ -31,26 +31,32 @@
(yet unknown) type, the exact type is detected at run-time.
Open issues:
- * untested on actual hardware
- * use 16-bit pixel format, currently pixels are converted to a 32-bit pixel
- format in lcd_update_rect, that is not natively supported yet in Rockbox.
+ * LCD is currently in portrait mode instead of landscape mode
+ * This LCD driver accesses the Rockbox framebuffer directly, so any changes
+ to the framebuffer as shown directly even before lcd_update is called.
+ * Sometimes part of the top of the screen appears at the bottom
+ * The Meizu seems to hang after LCD initialisation
+ * The driver for the S6D0139 LCD has not been tested yet
*/
/* LCD SPI connections */
-#define LCD_SPI_SSn (1<<1) /* on PDAT7 */
-#define LCD_SPI_MISO (1<<2) /* on PDAT3 */
-#define LCD_SPI_MOSI (1<<6) /* on PDAT3 */
-#define LCD_SPI_SCLK (1<<7) /* on PDAT3 */
-
-#define LCD_TYPE1_ID 0x139 /* id for LCD type S6D0139 */
-
+#define LCD_SPI_SSn (1<<1) /* on PDAT7 */
+#define LCD_SPI_MISO (1<<2) /* on PDAT3 */
+#define LCD_SPI_MOSI (1<<6) /* on PDAT3 */
+#define LCD_SPI_SCLK (1<<7) /* on PDAT3 */
+
+/* LCD SPI communication definitions */
+#define LCD_SPI_DEVICE_ID (0x1D<<2)
+#define LCD_SPI_INDEX_WRITE (LCD_SPI_DEVICE_ID|0)
+#define LCD_SPI_STATUS_READ (LCD_SPI_DEVICE_ID|1)
+#define LCD_SPI_DATA_WRITE (LCD_SPI_DEVICE_ID|2)
+#define LCD_SPI_DATA_READ (LCD_SPI_DEVICE_ID|3)
+
+#define LCD_TYPE1_ID 0x139 /* id for LCD type S6D0139 */
+
static int lcd_type = 0;
-/* local frame buffer, keeps pixels in 32-bit words in format 0x00RRGGBB */
-static uint32_t lcd_local_fb[LCD_HEIGHT][LCD_WIDTH];
-
-
/* simple and crude delay */
static void lcd_delay(int count)
{
@@ -111,7 +117,7 @@ static void lcd_spi_init(void)
/* configure MISO (P3.2) input, MOSI (P3.6) output, SCLK (P3.7) output */
PCON3 = (PCON3 & ~0xFF000F00) | 0x11000000;
-
+
/* set all outputs high */
PDAT7 |= LCD_SPI_SSn;
PDAT3 |= (LCD_SPI_MOSI | LCD_SPI_SCLK);
@@ -121,17 +127,17 @@ static void lcd_spi_init(void)
static unsigned int lcd_read_reg(unsigned reg)
{
unsigned int data;
-
- lcd_spi_transfer(24, (0x74 << 16) | reg); //0111.0100
- data = lcd_spi_transfer(24, (0x77 << 16)); //0111.0111
+
+ lcd_spi_transfer(24, (LCD_SPI_INDEX_WRITE << 16) | reg);
+ data = lcd_spi_transfer(24, (LCD_SPI_DATA_READ << 16));
return data & 0xFFFF;
}
/* write LCD register over SPI */
static void lcd_write_reg(unsigned char reg, unsigned int data)
-{
- lcd_spi_transfer(24, (0x74 << 16) | reg); //0111.0100
- lcd_spi_transfer(24, (0x76 << 16) | data); //0111.0110
+{
+ lcd_spi_transfer(24, (LCD_SPI_INDEX_WRITE << 16) | reg);
+ lcd_spi_transfer(24, (LCD_SPI_DATA_WRITE << 16) | data);
}
/* enable/disable clock signals towards the lcd */
@@ -226,10 +232,10 @@ static void lcd_init2(void)
lcd_write_reg(0x0C, 0x0000);
lcd_write_reg(0x0D, 0x0007);
lcd_write_reg(0x15, 0x0003);
-
lcd_write_reg(0x16, 0x0014);
- lcd_write_reg(0x17, 0x0000);
- lcd_write_reg(0x30, 0x0503);
+ lcd_write_reg(0x17, 0x0000);
+
+ lcd_write_reg(0x30, 0x0503); /* gamma? */
lcd_write_reg(0x31, 0x0303);
lcd_write_reg(0x32, 0x0305);
lcd_write_reg(0x33, 0x0202);
@@ -295,6 +301,8 @@ static void lcd_enable2(bool on)
lcd_write_reg(0x13, 0x0022);
lcd_write_reg(0x14, 0x0000);
lcd_write_reg(0x10, 0x7404);
+ lcd_write_reg(0x11, 0x0738);
+ lcd_write_reg(0x10, 0x7404);
lcd_delay(833350);
lcd_write_reg(0x07, 0x0009);
@@ -311,7 +319,7 @@ static void lcd_enable2(bool on)
lcd_write_reg(0x07, 0x010B);
}
else {
- lcd_write_reg(0x0B, 0x0000);
+ lcd_write_reg(0x0B, 0x0109);
lcd_write_reg(0x07, 0x0009);
lcd_delay(666680);
@@ -326,7 +334,7 @@ static void lcd_enable2(bool on)
/* turn both the lcd controller and the lcd itself on or off */
void lcd_enable(bool on)
-{
+{
if (on) {
/* enable controller clock */
PWRCON &= ~(1 << 18);
@@ -354,16 +362,28 @@ void lcd_enable(bool on)
/* initialise the lcd controller inside the s5l8700 */
static void lcd_controller_init(void)
{
- PWRCON &= ~(1 << 18);
-
- LCDCON1 = 0x991DC;
- LCDCON2 = 0xE8;
- LCDTCON1 = (lcd_type == 1) ? 0x70103 : 0x30303;
- LCDTCON2 = (lcd_type == 1) ? 0x70103 : 0x30703;
- LCDTCON3 = 0x9F8EF;
+ PWRCON &= ~(1 << 18);
+
+ LCDCON1 = (0 << 28) | /* BURSTLEN */
+ (0 << 19) | /* DIVEN */
+ (12 << 13) | /* CLKVAL */
+ (1 << 12) | /* CLKDIR, 1=divided clock */
+ (0 << 11) | /* CLKSEL, 0=HCLK, 1=PLL */
+ (5 << 6) | /* BPPMODEF, 5=rgb565, 7=raw24 */
+ (5 << 2) | /* BPPMODEB, 5=rgb565, 7=raw24 */
+ (0 << 0); /* ENVID */
+ LCDCON2 = (2 << 9) | /* PALFRM, 2=rgb565 palette */
+ (1 << 7) | /* IVCLK */
+ (1 << 6) | /* IHSYNC */
+ (1 << 5) | /* IVSYNC */
+ (1 << 3); /* IVDEN */
+ LCDTCON1 = (lcd_type == 1) ? 0x070103 : 0x030303;
+ LCDTCON2 = (lcd_type == 1) ? 0x070103 : 0x030703;
+ LCDTCON3 = ((LCD_HEIGHT - 1) << 11) | (LCD_WIDTH - 1);
LCDOSD1 = 0;
LCDOSD2 = 0;
- LCDOSD3 = 0;
+ LCDOSD3 = 0;
+
LCDB1SADDR1 = 0;
LCDB2SADDR1 = 0;
LCDF1SADDR1 = 0;
@@ -376,6 +396,7 @@ static void lcd_controller_init(void)
LCDB2SADDR3 = 0;
LCDF1SADDR3 = 0;
LCDF2SADDR3 = 0;
+
LCDKEYCON = 0;
LCDCOLVAL = 0;
LCDBGCON = 0;
@@ -387,21 +408,16 @@ static void lcd_controller_init(void)
void lcd_init_device(void)
{
- unsigned int lcd_id;
-
+ unsigned int lcd_id;
+ uint32_t fb, fb_end, window;
+
/* configure LCD SPI pins */
lcd_spi_init();
/* identify display through SPI */
lcd_id = lcd_read_reg(0);
- lcd_type = (lcd_id == LCD_TYPE1_ID) ? 1 : 2;
-
- /* configure LCD pins */
- PCON_ASRAM = 1;
+ lcd_type = (lcd_id == LCD_TYPE1_ID) ? 1 : 2;
- /* init LCD controller */
- lcd_controller_init();
-
/* display specific init sequence */
if (lcd_type == 1) {
lcd_init1();
@@ -409,35 +425,42 @@ void lcd_init_device(void)
else {
lcd_init2();
}
+
+ /* init LCD controller */
+ lcd_controller_init();
+
+ /* set framebuffer addresses */
+ fb = (uint32_t) &lcd_framebuffer[0][0];
+ fb_end = (uint32_t) &lcd_framebuffer[LCD_HEIGHT][0];
+ window = 2 * LCD_WIDTH;
+
+ LCDB1SADDR1 = fb;
+ LCDB2SADDR1 = fb;
+ LCDF1SADDR1 = fb;
+ LCDF2SADDR1 = fb;
+
+ LCDB1SADDR2 = fb_end;
+ LCDB2SADDR2 = fb_end;
+ LCDF1SADDR2 = fb_end; LCDF2SADDR2 = fb_end;
+
+ LCDB1SADDR3 = window;
+ LCDB2SADDR3 = window;
+ LCDF1SADDR3 = window;
+ LCDF2SADDR3 = window;
- /* set active background buffer */
- LCDCON1 &= ~(1 << 21); /* clear BDBCON */
-
- /* set background buffer address */
- LCDB1SADDR1 = (uint32_t) &lcd_local_fb[0][0];
- LCDB1SADDR2 = (uint32_t) &lcd_local_fb[LCD_HEIGHT][0];
-
- lcd_enable(true);
+ lcd_enable(true);
+
+ /* configure LCD pins */
+ PCON_ASRAM = 1;
}
void lcd_update_rect(int x, int y, int width, int height)
{
- fb_data *src;
- uint32_t *dst;
- fb_data pixel;
- int h, w;
-
- for (h = 0; h < height; h++) {
- src = &lcd_framebuffer[y][x];
- dst = &lcd_local_fb[y][x];
- for (w = 0; w < width; w++) {
- pixel = src[w];
- dst[w] = (RGB_UNPACK_RED(pixel) << 16) |
- (RGB_UNPACK_GREEN(pixel) << 8) |
- (RGB_UNPACK_BLUE(pixel) << 0);
- }
- y++;
- }
+ /* not implemented yet, LCD controller accesses framebuffer directly */
+ (void) x;
+ (void) y;
+ (void) width;
+ (void) height;
}
void lcd_update(void)