blob: df48326b5755566d206188cae6ce6ad877d62e7b [file] [log] [blame]
#include <common.h>
#include <malloc.h>
#include <asm/gpio.h>
/* Only support 3-wire 9bits spi-lcd for now */
#define LCD_SUB_ID_CNT 3
static u8 sub_id_reg[LCD_SUB_ID_CNT] = {0xDA, 0xDB, 0xDC};
struct lcd_sub_id {
u8 val;
u8 mask;
};
struct lcd_info {
const char *name;
u8 type;
struct lcd_sub_id sub_id[LCD_SUB_ID_CNT];
};
static struct lcd_info lcd_info[] = {
{"st7735", 1, {{0x7C, 0x7F}, {0x89, 0xFE}, {0xF0, 0xFF}} },
};
static inline void SPI_DELAY(u16 a)
{
while (a--)
nop();
}
static inline void SPI_CS(u16 a)
{
gpio_direction_output(CONFIG_SPI_CS_PIN, a);
}
static inline void SPI_SCL(u16 a)
{
gpio_direction_output(CONFIG_SPI_SCL_PIN, a);
}
static inline void SPI_TX(u16 a)
{
gpio_direction_output(CONFIG_SPI_TX_PIN, a);
}
static inline u8 SPI_READ(void)
{
return !!gpio_get_value(CONFIG_SPI_TX_PIN);
}
static inline void SPI_TX_TO_RX(void)
{
gpio_direction_input(CONFIG_SPI_TX_PIN);
}
static u8 __lcd_readid(u8 reg)
{
SPI_CS(0);
u16 cmd = reg;
int i;
/* May need to tune this delay for different panel.
* For ST7735, this delay can be set to 0.
*/
u16 delay = 0;
for (i = 0; i < 9; i++)
{
SPI_TX(cmd & 0x100);
SPI_DELAY(delay);
SPI_SCL(1);
SPI_DELAY(delay);
SPI_SCL(0);
cmd <<= 1;
}
SPI_TX_TO_RX();
cmd = 0;
for (i = 0; i < 8; i++)
{
SPI_DELAY(delay);
SPI_SCL(1);
cmd <<= 1;
cmd |= SPI_READ();
SPI_SCL(0);
}
SPI_CS(1);
printf("LCD ID 0x%x: 0x%x\n", reg, cmd);
return cmd;
}
static void do_lcd_rst(void)
{
gpio_direction_output(CONFIG_LCD_RST_PIN, 1);
mdelay(50);
gpio_direction_output(CONFIG_LCD_RST_PIN, 0);
mdelay(50);
gpio_direction_output(CONFIG_LCD_RST_PIN, 1);
mdelay(150);
}
static u8 check_id(u8 id, u8 mask, u8 val)
{
if ((val & mask) == (id & mask))
return 0;
return 1;
}
u8 lcd_gettype(void)
{
u32 id = 0;
int i;
u8 id1, id2, id3;
u8 type = 0;
lcd_readid_pin_config();
do_lcd_rst();
for (i = 0; i < LCD_SUB_ID_CNT; i++) {
id <<= 8;
id |= __lcd_readid(sub_id_reg[i]);
}
lcd_readid_pin_restore();
id1 = (id & 0xFF0000) >> 16;
id2 = (id & 0xFF00) >> 8;
id3 = id & 0xFF;
for (i = 0; i < sizeof(lcd_info) / sizeof(lcd_info[0]); i++) {
if (check_id(id1, lcd_info[i].sub_id[0].mask, lcd_info[i].sub_id[0].val) == 0 &&
check_id(id2, lcd_info[i].sub_id[1].mask, lcd_info[i].sub_id[1].val) == 0 &&
check_id(id3, lcd_info[i].sub_id[2].mask, lcd_info[i].sub_id[2].val) == 0)
{
printf("LCD Name: %s, ID: 0x%x, Type: %d\n",
lcd_info[i].name, id, lcd_info[i].type);
type = lcd_info[i].type;
goto end;
}
}
printf("UNSUPPORTTED LCD ID: 0x%x, Type: 0\n", id);
end:
return type;
}