| #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; |
| } |