summaryrefslogtreecommitdiff
path: root/firmware/target
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target')
-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 @@
31 (yet unknown) type, the exact type is detected at run-time. 31 (yet unknown) type, the exact type is detected at run-time.
32 32
33 Open issues: 33 Open issues:
34 * untested on actual hardware 34 * LCD is currently in portrait mode instead of landscape mode
35 * use 16-bit pixel format, currently pixels are converted to a 32-bit pixel 35 * This LCD driver accesses the Rockbox framebuffer directly, so any changes
36 format in lcd_update_rect, that is not natively supported yet in Rockbox. 36 to the framebuffer as shown directly even before lcd_update is called.
37 * Sometimes part of the top of the screen appears at the bottom
38 * The Meizu seems to hang after LCD initialisation
39 * The driver for the S6D0139 LCD has not been tested yet
37 40
38 */ 41 */
39 42
40/* LCD SPI connections */ 43/* LCD SPI connections */
41#define LCD_SPI_SSn (1<<1) /* on PDAT7 */ 44#define LCD_SPI_SSn (1<<1) /* on PDAT7 */
42#define LCD_SPI_MISO (1<<2) /* on PDAT3 */ 45#define LCD_SPI_MISO (1<<2) /* on PDAT3 */
43#define LCD_SPI_MOSI (1<<6) /* on PDAT3 */ 46#define LCD_SPI_MOSI (1<<6) /* on PDAT3 */
44#define LCD_SPI_SCLK (1<<7) /* on PDAT3 */ 47#define LCD_SPI_SCLK (1<<7) /* on PDAT3 */
45 48
46#define LCD_TYPE1_ID 0x139 /* id for LCD type S6D0139 */ 49/* LCD SPI communication definitions */
47 50#define LCD_SPI_DEVICE_ID (0x1D<<2)
51#define LCD_SPI_INDEX_WRITE (LCD_SPI_DEVICE_ID|0)
52#define LCD_SPI_STATUS_READ (LCD_SPI_DEVICE_ID|1)
53#define LCD_SPI_DATA_WRITE (LCD_SPI_DEVICE_ID|2)
54#define LCD_SPI_DATA_READ (LCD_SPI_DEVICE_ID|3)
55
56#define LCD_TYPE1_ID 0x139 /* id for LCD type S6D0139 */
57
48static int lcd_type = 0; 58static int lcd_type = 0;
49 59
50/* local frame buffer, keeps pixels in 32-bit words in format 0x00RRGGBB */
51static uint32_t lcd_local_fb[LCD_HEIGHT][LCD_WIDTH];
52
53
54/* simple and crude delay */ 60/* simple and crude delay */
55static void lcd_delay(int count) 61static void lcd_delay(int count)
56{ 62{
@@ -111,7 +117,7 @@ static void lcd_spi_init(void)
111 117
112 /* configure MISO (P3.2) input, MOSI (P3.6) output, SCLK (P3.7) output */ 118 /* configure MISO (P3.2) input, MOSI (P3.6) output, SCLK (P3.7) output */
113 PCON3 = (PCON3 & ~0xFF000F00) | 0x11000000; 119 PCON3 = (PCON3 & ~0xFF000F00) | 0x11000000;
114 120
115 /* set all outputs high */ 121 /* set all outputs high */
116 PDAT7 |= LCD_SPI_SSn; 122 PDAT7 |= LCD_SPI_SSn;
117 PDAT3 |= (LCD_SPI_MOSI | LCD_SPI_SCLK); 123 PDAT3 |= (LCD_SPI_MOSI | LCD_SPI_SCLK);
@@ -121,17 +127,17 @@ static void lcd_spi_init(void)
121static unsigned int lcd_read_reg(unsigned reg) 127static unsigned int lcd_read_reg(unsigned reg)
122{ 128{
123 unsigned int data; 129 unsigned int data;
124 130
125 lcd_spi_transfer(24, (0x74 << 16) | reg); //0111.0100 131 lcd_spi_transfer(24, (LCD_SPI_INDEX_WRITE << 16) | reg);
126 data = lcd_spi_transfer(24, (0x77 << 16)); //0111.0111 132 data = lcd_spi_transfer(24, (LCD_SPI_DATA_READ << 16));
127 return data & 0xFFFF; 133 return data & 0xFFFF;
128} 134}
129 135
130/* write LCD register over SPI */ 136/* write LCD register over SPI */
131static void lcd_write_reg(unsigned char reg, unsigned int data) 137static void lcd_write_reg(unsigned char reg, unsigned int data)
132{ 138{
133 lcd_spi_transfer(24, (0x74 << 16) | reg); //0111.0100 139 lcd_spi_transfer(24, (LCD_SPI_INDEX_WRITE << 16) | reg);
134 lcd_spi_transfer(24, (0x76 << 16) | data); //0111.0110 140 lcd_spi_transfer(24, (LCD_SPI_DATA_WRITE << 16) | data);
135} 141}
136 142
137/* enable/disable clock signals towards the lcd */ 143/* enable/disable clock signals towards the lcd */
@@ -226,10 +232,10 @@ static void lcd_init2(void)
226 lcd_write_reg(0x0C, 0x0000); 232 lcd_write_reg(0x0C, 0x0000);
227 lcd_write_reg(0x0D, 0x0007); 233 lcd_write_reg(0x0D, 0x0007);
228 lcd_write_reg(0x15, 0x0003); 234 lcd_write_reg(0x15, 0x0003);
229
230 lcd_write_reg(0x16, 0x0014); 235 lcd_write_reg(0x16, 0x0014);
231 lcd_write_reg(0x17, 0x0000); 236 lcd_write_reg(0x17, 0x0000);
232 lcd_write_reg(0x30, 0x0503); 237
238 lcd_write_reg(0x30, 0x0503); /* gamma? */
233 lcd_write_reg(0x31, 0x0303); 239 lcd_write_reg(0x31, 0x0303);
234 lcd_write_reg(0x32, 0x0305); 240 lcd_write_reg(0x32, 0x0305);
235 lcd_write_reg(0x33, 0x0202); 241 lcd_write_reg(0x33, 0x0202);
@@ -295,6 +301,8 @@ static void lcd_enable2(bool on)
295 lcd_write_reg(0x13, 0x0022); 301 lcd_write_reg(0x13, 0x0022);
296 lcd_write_reg(0x14, 0x0000); 302 lcd_write_reg(0x14, 0x0000);
297 lcd_write_reg(0x10, 0x7404); 303 lcd_write_reg(0x10, 0x7404);
304 lcd_write_reg(0x11, 0x0738);
305 lcd_write_reg(0x10, 0x7404);
298 lcd_delay(833350); 306 lcd_delay(833350);
299 307
300 lcd_write_reg(0x07, 0x0009); 308 lcd_write_reg(0x07, 0x0009);
@@ -311,7 +319,7 @@ static void lcd_enable2(bool on)
311 lcd_write_reg(0x07, 0x010B); 319 lcd_write_reg(0x07, 0x010B);
312 } 320 }
313 else { 321 else {
314 lcd_write_reg(0x0B, 0x0000); 322 lcd_write_reg(0x0B, 0x0109);
315 lcd_write_reg(0x07, 0x0009); 323 lcd_write_reg(0x07, 0x0009);
316 lcd_delay(666680); 324 lcd_delay(666680);
317 325
@@ -326,7 +334,7 @@ static void lcd_enable2(bool on)
326 334
327/* turn both the lcd controller and the lcd itself on or off */ 335/* turn both the lcd controller and the lcd itself on or off */
328void lcd_enable(bool on) 336void lcd_enable(bool on)
329{ 337{
330 if (on) { 338 if (on) {
331 /* enable controller clock */ 339 /* enable controller clock */
332 PWRCON &= ~(1 << 18); 340 PWRCON &= ~(1 << 18);
@@ -354,16 +362,28 @@ void lcd_enable(bool on)
354/* initialise the lcd controller inside the s5l8700 */ 362/* initialise the lcd controller inside the s5l8700 */
355static void lcd_controller_init(void) 363static void lcd_controller_init(void)
356{ 364{
357 PWRCON &= ~(1 << 18); 365 PWRCON &= ~(1 << 18);
358 366
359 LCDCON1 = 0x991DC; 367 LCDCON1 = (0 << 28) | /* BURSTLEN */
360 LCDCON2 = 0xE8; 368 (0 << 19) | /* DIVEN */
361 LCDTCON1 = (lcd_type == 1) ? 0x70103 : 0x30303; 369 (12 << 13) | /* CLKVAL */
362 LCDTCON2 = (lcd_type == 1) ? 0x70103 : 0x30703; 370 (1 << 12) | /* CLKDIR, 1=divided clock */
363 LCDTCON3 = 0x9F8EF; 371 (0 << 11) | /* CLKSEL, 0=HCLK, 1=PLL */
372 (5 << 6) | /* BPPMODEF, 5=rgb565, 7=raw24 */
373 (5 << 2) | /* BPPMODEB, 5=rgb565, 7=raw24 */
374 (0 << 0); /* ENVID */
375 LCDCON2 = (2 << 9) | /* PALFRM, 2=rgb565 palette */
376 (1 << 7) | /* IVCLK */
377 (1 << 6) | /* IHSYNC */
378 (1 << 5) | /* IVSYNC */
379 (1 << 3); /* IVDEN */
380 LCDTCON1 = (lcd_type == 1) ? 0x070103 : 0x030303;
381 LCDTCON2 = (lcd_type == 1) ? 0x070103 : 0x030703;
382 LCDTCON3 = ((LCD_HEIGHT - 1) << 11) | (LCD_WIDTH - 1);
364 LCDOSD1 = 0; 383 LCDOSD1 = 0;
365 LCDOSD2 = 0; 384 LCDOSD2 = 0;
366 LCDOSD3 = 0; 385 LCDOSD3 = 0;
386
367 LCDB1SADDR1 = 0; 387 LCDB1SADDR1 = 0;
368 LCDB2SADDR1 = 0; 388 LCDB2SADDR1 = 0;
369 LCDF1SADDR1 = 0; 389 LCDF1SADDR1 = 0;
@@ -376,6 +396,7 @@ static void lcd_controller_init(void)
376 LCDB2SADDR3 = 0; 396 LCDB2SADDR3 = 0;
377 LCDF1SADDR3 = 0; 397 LCDF1SADDR3 = 0;
378 LCDF2SADDR3 = 0; 398 LCDF2SADDR3 = 0;
399
379 LCDKEYCON = 0; 400 LCDKEYCON = 0;
380 LCDCOLVAL = 0; 401 LCDCOLVAL = 0;
381 LCDBGCON = 0; 402 LCDBGCON = 0;
@@ -387,21 +408,16 @@ static void lcd_controller_init(void)
387 408
388void lcd_init_device(void) 409void lcd_init_device(void)
389{ 410{
390 unsigned int lcd_id; 411 unsigned int lcd_id;
391 412 uint32_t fb, fb_end, window;
413
392 /* configure LCD SPI pins */ 414 /* configure LCD SPI pins */
393 lcd_spi_init(); 415 lcd_spi_init();
394 416
395 /* identify display through SPI */ 417 /* identify display through SPI */
396 lcd_id = lcd_read_reg(0); 418 lcd_id = lcd_read_reg(0);
397 lcd_type = (lcd_id == LCD_TYPE1_ID) ? 1 : 2; 419 lcd_type = (lcd_id == LCD_TYPE1_ID) ? 1 : 2;
398
399 /* configure LCD pins */
400 PCON_ASRAM = 1;
401 420
402 /* init LCD controller */
403 lcd_controller_init();
404
405 /* display specific init sequence */ 421 /* display specific init sequence */
406 if (lcd_type == 1) { 422 if (lcd_type == 1) {
407 lcd_init1(); 423 lcd_init1();
@@ -409,35 +425,42 @@ void lcd_init_device(void)
409 else { 425 else {
410 lcd_init2(); 426 lcd_init2();
411 } 427 }
428
429 /* init LCD controller */
430 lcd_controller_init();
431
432 /* set framebuffer addresses */
433 fb = (uint32_t) &lcd_framebuffer[0][0];
434 fb_end = (uint32_t) &lcd_framebuffer[LCD_HEIGHT][0];
435 window = 2 * LCD_WIDTH;
436
437 LCDB1SADDR1 = fb;
438 LCDB2SADDR1 = fb;
439 LCDF1SADDR1 = fb;
440 LCDF2SADDR1 = fb;
441
442 LCDB1SADDR2 = fb_end;
443 LCDB2SADDR2 = fb_end;
444 LCDF1SADDR2 = fb_end; LCDF2SADDR2 = fb_end;
445
446 LCDB1SADDR3 = window;
447 LCDB2SADDR3 = window;
448 LCDF1SADDR3 = window;
449 LCDF2SADDR3 = window;
412 450
413 /* set active background buffer */ 451 lcd_enable(true);
414 LCDCON1 &= ~(1 << 21); /* clear BDBCON */ 452
415 453 /* configure LCD pins */
416 /* set background buffer address */ 454 PCON_ASRAM = 1;
417 LCDB1SADDR1 = (uint32_t) &lcd_local_fb[0][0];
418 LCDB1SADDR2 = (uint32_t) &lcd_local_fb[LCD_HEIGHT][0];
419
420 lcd_enable(true);
421} 455}
422 456
423void lcd_update_rect(int x, int y, int width, int height) 457void lcd_update_rect(int x, int y, int width, int height)
424{ 458{
425 fb_data *src; 459 /* not implemented yet, LCD controller accesses framebuffer directly */
426 uint32_t *dst; 460 (void) x;
427 fb_data pixel; 461 (void) y;
428 int h, w; 462 (void) width;
429 463 (void) height;
430 for (h = 0; h < height; h++) {
431 src = &lcd_framebuffer[y][x];
432 dst = &lcd_local_fb[y][x];
433 for (w = 0; w < width; w++) {
434 pixel = src[w];
435 dst[w] = (RGB_UNPACK_RED(pixel) << 16) |
436 (RGB_UNPACK_GREEN(pixel) << 8) |
437 (RGB_UNPACK_BLUE(pixel) << 0);
438 }
439 y++;
440 }
441} 464}
442 465
443void lcd_update(void) 466void lcd_update(void)