blob: 75f2891fa26be98e94ac34662e1d4c8ad7d186d0 [file] [log] [blame]
#include <asm/gpio.h>
#include <malloc.h>
#include <spi.h>
#include "lcd.h"
#include "st7735.c"
#include "gc9106.c"
#include "logo.c"
#ifdef CONFIG_SPI_LCD_3WIRE
#define FB_SIZE (CONFIG_SPI_LCD_XRES * CONFIG_SPI_LCD_YRES * 2 * 2)
#else
#define FB_SIZE (CONFIG_SPI_LCD_XRES * CONFIG_SPI_LCD_YRES * 2)
#endif
static u8 *gFramebuffer = NULL;
static struct spi_slave *gSpiSlave = NULL;
void lcd_power(bool on)
{
#ifdef CONFIG_SPI_LCD_POWER_PIN
gpio_direction_output(CONFIG_SPI_LCD_POWER_PIN, on);
#endif
}
void lcd_reset(void)
{
gpio_direction_output(CONFIG_SPI_LCD_RST_PIN, 1);
mdelay(50);
gpio_direction_output(CONFIG_SPI_LCD_RST_PIN, 0);
mdelay(50);
gpio_direction_output(CONFIG_SPI_LCD_RST_PIN, 1);
mdelay(150);
}
static void lcd_set_backlight(bool on)
{
gpio_direction_output(CONFIG_SPI_LCD_BL_PIN, on);
}
static int lcd_write_cmd(u8 cmd)
{
int ret;
u16 bits, _data;
#ifdef CONFIG_SPI_LCD_3WIRE
bits = 9;
_data = cmd;
#else
bits = 8;
_data = cmd;
LCD_SEND_CMD();
#endif
ret = spi_xfer(gSpiSlave, bits, &_data, NULL,
SPI_XFER_BEGIN | SPI_XFER_END);
if (ret)
printf("SPILCD: Failed to send command %d\n", cmd);
return ret;
}
static int lcd_write_data(u8 data)
{
int ret;
u16 bits, _data;
#ifdef CONFIG_SPI_LCD_3WIRE
bits = 9;
_data = 0x100 | data;
#else
bits = 8;
_data = data;
LCD_SEND_DATA();
#endif
ret = spi_xfer(gSpiSlave, bits, &_data, NULL,
SPI_XFER_BEGIN | SPI_XFER_END);
if (ret)
printf("Lcd: Failed to send data.\n");
return ret;
}
static int lcd_write_data_buffer(u8 *txbuf, int size)
{
int ret;
u16 bits;
#ifdef CONFIG_SPI_LCD_3WIRE
bits = 9;
#else
bits = 8;
LCD_SEND_DATA();
#endif
ret = spi_xfer(gSpiSlave, bits * size, txbuf, NULL,
SPI_XFER_BEGIN | SPI_XFER_END);
if (ret)
printf("Lcd: Failed to send data.\n");
return ret;
}
static int lcd_set_window(u8 xs, u8 ys, u8 xe, u8 ye)
{
lcd_write_cmd(0x2a); // column addr set
lcd_write_data(0x00);
lcd_write_data(xs);
lcd_write_data(0x00);
lcd_write_data(xe);
lcd_write_cmd(0x2b); // row addr set
lcd_write_data(0x00);
lcd_write_data(ys);
lcd_write_data(0x00);
lcd_write_data(ye);
return 0;
}
static int lcd_write_memory(u8 *buf, int cnt)
{
int i;
lcd_write_cmd(0x2c); // memory write command
#if 1
for (i = 0; i < cnt; i++) {
lcd_write_data(buf[i]);
}
#else
lcd_write_data_buffer(buf, cnt);
#endif
return 0;
}
static int lcd_fill(u16 color)
{
u8 x, y, low, high;
u16 *buf = (u16 *)gFramebuffer;
memset(buf, 0, FB_SIZE);
lcd_set_window(0, 0, CONFIG_SPI_LCD_XRES - 1, CONFIG_SPI_LCD_YRES - 1);
for (x=0; x < CONFIG_SPI_LCD_XRES; x++)
for (y=0; y < CONFIG_SPI_LCD_YRES; y++) {
low = color & 0xff;
high = (color & 0xff00) >> 8;
#ifdef CONFIG_SPI_LCD_3WIRE
*(buf++) = low;
*(buf++) = high;
#else
*(buf++) = (low << 8) | high;
#endif
}
return lcd_write_memory(gFramebuffer, FB_SIZE);
}
static int lcd_draw_logo(
u8 p_x, u8 line,
u8 W, u8 H,
u8 *buf, u16 txt_color, u16 bg_color)
{
int i, j, k;
u8 c;
int index, size;
u16 *buff = (u16 *)gFramebuffer;
lcd_set_window(line, p_x, (line + H - 1), (p_x + W - 1));
index = 0;
for(i = 0; i < W; i++) {
for(k = (H / 8 -1); k >= 0; k--) {
c = *buf++;
for(j = (8 - 1); j >= 0; j--) {
if((1 << (7 - j)) & c)
*(buff++) = txt_color;
else
*(buff++) = bg_color;
index++;
}
}
}
size = index;
return lcd_write_memory(gFramebuffer, size * 2);
}
static void panel_init(void *sequence)
{
struct lcd_cmd *array = (struct lcd_cmd *)sequence;
if (!array) {
printf("Warning: null init sequence.\n");
return;
}
while (array->type != CMD_TYPE_END) {
switch (array->type) {
case CMD_TYPE_START:
break;
case CMD_TYPE_CMD:
lcd_write_cmd(array->data);
break;
case CMD_TYPE_DATA:
lcd_write_data(array->data);
break;
case CMD_TYPE_DELAY:
mdelay(array->data);
break;
}
array++;
}
printf("Panel: init done.\n");
}
int spi_lcd_init(void)
{
int ret;
int bus = 0;
int panel;
void *seq = NULL;
panel = lcd_gettype();
gFramebuffer = malloc(FB_SIZE);
spi_init();
gSpiSlave = spi_setup_slave(bus, CONFIG_SPI_LCD_CS_PIN, 0, SPI_MODE_3);
if (!gSpiSlave) {
printf("Lcd: Failed to set up slave\n");
return -1;
}
ret = spi_claim_bus(gSpiSlave);
if (ret) {
printf("Lcd: Failed to claim SPI bus: %d\n", ret);
return -1;
}
#ifdef CONFIG_SPI_LCD_3WIRE
spi_set_wordlen(gSpiSlave, 9);
#else
spi_set_wordlen(gSpiSlave, 8);
#endif
if (panel == PANEL_ST7735)
seq = st7735_init_sequence;
else if (panel == PANEL_GC9102)
/* use same seq as st7735 */
seq = st7735_init_sequence;
else if (panel == PANEL_GC9106)
seq = gc9106_init_sequence;
panel_init(seq);
#ifdef LCD_TEST
lcd_set_backlight(1);
lcd_fill(0xF800); // R
mdelay(1000);
lcd_fill(0x7E0); // G
mdelay(1000);
lcd_fill(0x1F); // B
#else
#ifdef CONFIG_SHOW_MARVELL_LOGO
lcd_draw_logo(0x20, 0x40, 0x40, 0x20,
(u8 *)marvell_logo, 0xffff, 0x0000);
#else
lcd_draw_logo(0x20, 0x40, 0x40, 0x20,
(u8 *)asr_logo, 0xffff, 0x0000);
#endif
lcd_set_backlight(1);
#endif
return panel;
}