mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-14 10:37:38 -04:00
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
This commit is contained in:
parent
f3944cb694
commit
52ca187f68
3 changed files with 97 additions and 70 deletions
|
@ -41,6 +41,7 @@
|
||||||
#include "rbunicode.h"
|
#include "rbunicode.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include "qt1106.h"
|
#include "qt1106.h"
|
||||||
|
#include "bitmaps/rockboxlogo.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
@ -107,7 +108,10 @@ void main(void)
|
||||||
oldval = PCON1;
|
oldval = PCON1;
|
||||||
PCON1 = ((oldval & ~(0xf << 16)) | (0 << 16));
|
PCON1 = ((oldval & ~(0xf << 16)) | (0 << 16));
|
||||||
|
|
||||||
// Wait for play to be pressed
|
lcd_bitmap(rockboxlogo, 0, 0, BMPWIDTH_rockboxlogo, BMPHEIGHT_rockboxlogo);
|
||||||
|
lcd_init_device();
|
||||||
|
|
||||||
|
// Wait for play to be pressed
|
||||||
while(!(PDAT1 & (1 << 4)));
|
while(!(PDAT1 & (1 << 4)));
|
||||||
// Wait for play to be released
|
// Wait for play to be released
|
||||||
while((PDAT1 & (1 << 4)));
|
while((PDAT1 & (1 << 4)));
|
||||||
|
|
|
@ -59,13 +59,13 @@
|
||||||
#define CONFIG_NAND NAND_SAMSUNG
|
#define CONFIG_NAND NAND_SAMSUNG
|
||||||
|
|
||||||
/* LCD dimensions */
|
/* LCD dimensions */
|
||||||
#define LCD_WIDTH 320
|
#define LCD_WIDTH 240
|
||||||
#define LCD_HEIGHT 240
|
#define LCD_HEIGHT 320
|
||||||
#define LCD_DEPTH 16 /* pseudo 262.144 colors */
|
#define LCD_DEPTH 16 /* pseudo 262.144 colors */
|
||||||
#define LCD_PIXELFORMAT RGB565 /* rgb565 */
|
#define LCD_PIXELFORMAT RGB565 /* rgb565 */
|
||||||
|
|
||||||
/* Define this if your LCD can be enabled/disabled */
|
/* Define this if your LCD can be enabled/disabled */
|
||||||
//#define HAVE_LCD_ENABLE
|
#define HAVE_LCD_ENABLE
|
||||||
|
|
||||||
/* Define this if your LCD can be put to sleep. HAVE_LCD_ENABLE
|
/* Define this if your LCD can be put to sleep. HAVE_LCD_ENABLE
|
||||||
should be defined as well. */
|
should be defined as well. */
|
||||||
|
|
|
@ -31,26 +31,32 @@
|
||||||
(yet unknown) type, the exact type is detected at run-time.
|
(yet unknown) type, the exact type is detected at run-time.
|
||||||
|
|
||||||
Open issues:
|
Open issues:
|
||||||
* untested on actual hardware
|
* LCD is currently in portrait mode instead of landscape mode
|
||||||
* use 16-bit pixel format, currently pixels are converted to a 32-bit pixel
|
* This LCD driver accesses the Rockbox framebuffer directly, so any changes
|
||||||
format in lcd_update_rect, that is not natively supported yet in Rockbox.
|
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 */
|
/* LCD SPI connections */
|
||||||
#define LCD_SPI_SSn (1<<1) /* on PDAT7 */
|
#define LCD_SPI_SSn (1<<1) /* on PDAT7 */
|
||||||
#define LCD_SPI_MISO (1<<2) /* on PDAT3 */
|
#define LCD_SPI_MISO (1<<2) /* on PDAT3 */
|
||||||
#define LCD_SPI_MOSI (1<<6) /* on PDAT3 */
|
#define LCD_SPI_MOSI (1<<6) /* on PDAT3 */
|
||||||
#define LCD_SPI_SCLK (1<<7) /* on PDAT3 */
|
#define LCD_SPI_SCLK (1<<7) /* on PDAT3 */
|
||||||
|
|
||||||
#define LCD_TYPE1_ID 0x139 /* id for LCD type S6D0139 */
|
/* 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;
|
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 */
|
/* simple and crude delay */
|
||||||
static void lcd_delay(int count)
|
static void lcd_delay(int count)
|
||||||
{
|
{
|
||||||
|
@ -122,16 +128,16 @@ static unsigned int lcd_read_reg(unsigned reg)
|
||||||
{
|
{
|
||||||
unsigned int data;
|
unsigned int data;
|
||||||
|
|
||||||
lcd_spi_transfer(24, (0x74 << 16) | reg); //0111.0100
|
lcd_spi_transfer(24, (LCD_SPI_INDEX_WRITE << 16) | reg);
|
||||||
data = lcd_spi_transfer(24, (0x77 << 16)); //0111.0111
|
data = lcd_spi_transfer(24, (LCD_SPI_DATA_READ << 16));
|
||||||
return data & 0xFFFF;
|
return data & 0xFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write LCD register over SPI */
|
/* write LCD register over SPI */
|
||||||
static void lcd_write_reg(unsigned char reg, unsigned int data)
|
static void lcd_write_reg(unsigned char reg, unsigned int data)
|
||||||
{
|
{
|
||||||
lcd_spi_transfer(24, (0x74 << 16) | reg); //0111.0100
|
lcd_spi_transfer(24, (LCD_SPI_INDEX_WRITE << 16) | reg);
|
||||||
lcd_spi_transfer(24, (0x76 << 16) | data); //0111.0110
|
lcd_spi_transfer(24, (LCD_SPI_DATA_WRITE << 16) | data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* enable/disable clock signals towards the lcd */
|
/* enable/disable clock signals towards the lcd */
|
||||||
|
@ -226,10 +232,10 @@ static void lcd_init2(void)
|
||||||
lcd_write_reg(0x0C, 0x0000);
|
lcd_write_reg(0x0C, 0x0000);
|
||||||
lcd_write_reg(0x0D, 0x0007);
|
lcd_write_reg(0x0D, 0x0007);
|
||||||
lcd_write_reg(0x15, 0x0003);
|
lcd_write_reg(0x15, 0x0003);
|
||||||
|
|
||||||
lcd_write_reg(0x16, 0x0014);
|
lcd_write_reg(0x16, 0x0014);
|
||||||
lcd_write_reg(0x17, 0x0000);
|
lcd_write_reg(0x17, 0x0000);
|
||||||
lcd_write_reg(0x30, 0x0503);
|
|
||||||
|
lcd_write_reg(0x30, 0x0503); /* gamma? */
|
||||||
lcd_write_reg(0x31, 0x0303);
|
lcd_write_reg(0x31, 0x0303);
|
||||||
lcd_write_reg(0x32, 0x0305);
|
lcd_write_reg(0x32, 0x0305);
|
||||||
lcd_write_reg(0x33, 0x0202);
|
lcd_write_reg(0x33, 0x0202);
|
||||||
|
@ -295,6 +301,8 @@ static void lcd_enable2(bool on)
|
||||||
lcd_write_reg(0x13, 0x0022);
|
lcd_write_reg(0x13, 0x0022);
|
||||||
lcd_write_reg(0x14, 0x0000);
|
lcd_write_reg(0x14, 0x0000);
|
||||||
lcd_write_reg(0x10, 0x7404);
|
lcd_write_reg(0x10, 0x7404);
|
||||||
|
lcd_write_reg(0x11, 0x0738);
|
||||||
|
lcd_write_reg(0x10, 0x7404);
|
||||||
lcd_delay(833350);
|
lcd_delay(833350);
|
||||||
|
|
||||||
lcd_write_reg(0x07, 0x0009);
|
lcd_write_reg(0x07, 0x0009);
|
||||||
|
@ -311,7 +319,7 @@ static void lcd_enable2(bool on)
|
||||||
lcd_write_reg(0x07, 0x010B);
|
lcd_write_reg(0x07, 0x010B);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lcd_write_reg(0x0B, 0x0000);
|
lcd_write_reg(0x0B, 0x0109);
|
||||||
lcd_write_reg(0x07, 0x0009);
|
lcd_write_reg(0x07, 0x0009);
|
||||||
lcd_delay(666680);
|
lcd_delay(666680);
|
||||||
|
|
||||||
|
@ -356,14 +364,26 @@ static void lcd_controller_init(void)
|
||||||
{
|
{
|
||||||
PWRCON &= ~(1 << 18);
|
PWRCON &= ~(1 << 18);
|
||||||
|
|
||||||
LCDCON1 = 0x991DC;
|
LCDCON1 = (0 << 28) | /* BURSTLEN */
|
||||||
LCDCON2 = 0xE8;
|
(0 << 19) | /* DIVEN */
|
||||||
LCDTCON1 = (lcd_type == 1) ? 0x70103 : 0x30303;
|
(12 << 13) | /* CLKVAL */
|
||||||
LCDTCON2 = (lcd_type == 1) ? 0x70103 : 0x30703;
|
(1 << 12) | /* CLKDIR, 1=divided clock */
|
||||||
LCDTCON3 = 0x9F8EF;
|
(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;
|
LCDOSD1 = 0;
|
||||||
LCDOSD2 = 0;
|
LCDOSD2 = 0;
|
||||||
LCDOSD3 = 0;
|
LCDOSD3 = 0;
|
||||||
|
|
||||||
LCDB1SADDR1 = 0;
|
LCDB1SADDR1 = 0;
|
||||||
LCDB2SADDR1 = 0;
|
LCDB2SADDR1 = 0;
|
||||||
LCDF1SADDR1 = 0;
|
LCDF1SADDR1 = 0;
|
||||||
|
@ -376,6 +396,7 @@ static void lcd_controller_init(void)
|
||||||
LCDB2SADDR3 = 0;
|
LCDB2SADDR3 = 0;
|
||||||
LCDF1SADDR3 = 0;
|
LCDF1SADDR3 = 0;
|
||||||
LCDF2SADDR3 = 0;
|
LCDF2SADDR3 = 0;
|
||||||
|
|
||||||
LCDKEYCON = 0;
|
LCDKEYCON = 0;
|
||||||
LCDCOLVAL = 0;
|
LCDCOLVAL = 0;
|
||||||
LCDBGCON = 0;
|
LCDBGCON = 0;
|
||||||
|
@ -388,6 +409,7 @@ static void lcd_controller_init(void)
|
||||||
void lcd_init_device(void)
|
void lcd_init_device(void)
|
||||||
{
|
{
|
||||||
unsigned int lcd_id;
|
unsigned int lcd_id;
|
||||||
|
uint32_t fb, fb_end, window;
|
||||||
|
|
||||||
/* configure LCD SPI pins */
|
/* configure LCD SPI pins */
|
||||||
lcd_spi_init();
|
lcd_spi_init();
|
||||||
|
@ -396,12 +418,6 @@ void lcd_init_device(void)
|
||||||
lcd_id = lcd_read_reg(0);
|
lcd_id = lcd_read_reg(0);
|
||||||
lcd_type = (lcd_id == LCD_TYPE1_ID) ? 1 : 2;
|
lcd_type = (lcd_id == LCD_TYPE1_ID) ? 1 : 2;
|
||||||
|
|
||||||
/* configure LCD pins */
|
|
||||||
PCON_ASRAM = 1;
|
|
||||||
|
|
||||||
/* init LCD controller */
|
|
||||||
lcd_controller_init();
|
|
||||||
|
|
||||||
/* display specific init sequence */
|
/* display specific init sequence */
|
||||||
if (lcd_type == 1) {
|
if (lcd_type == 1) {
|
||||||
lcd_init1();
|
lcd_init1();
|
||||||
|
@ -410,34 +426,41 @@ void lcd_init_device(void)
|
||||||
lcd_init2();
|
lcd_init2();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set active background buffer */
|
/* init LCD controller */
|
||||||
LCDCON1 &= ~(1 << 21); /* clear BDBCON */
|
lcd_controller_init();
|
||||||
|
|
||||||
/* set background buffer address */
|
/* set framebuffer addresses */
|
||||||
LCDB1SADDR1 = (uint32_t) &lcd_local_fb[0][0];
|
fb = (uint32_t) &lcd_framebuffer[0][0];
|
||||||
LCDB1SADDR2 = (uint32_t) &lcd_local_fb[LCD_HEIGHT][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;
|
||||||
|
|
||||||
lcd_enable(true);
|
lcd_enable(true);
|
||||||
|
|
||||||
|
/* configure LCD pins */
|
||||||
|
PCON_ASRAM = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcd_update_rect(int x, int y, int width, int height)
|
void lcd_update_rect(int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
fb_data *src;
|
/* not implemented yet, LCD controller accesses framebuffer directly */
|
||||||
uint32_t *dst;
|
(void) x;
|
||||||
fb_data pixel;
|
(void) y;
|
||||||
int h, w;
|
(void) width;
|
||||||
|
(void) height;
|
||||||
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++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcd_update(void)
|
void lcd_update(void)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue