From: Haavard Skinnemoen <[EMAIL PROTECTED]> This adds mode definitions and initialization code for the on-board Samsung LTV350QV panel.
Signed-off-by: Haavard Skinnemoen <[EMAIL PROTECTED]> --- board/atmel/atstk1000/Makefile | 1 + board/atmel/atstk1000/ltv350qv.c | 157 ++++++++++++++++++++++++++++++++++++++ board/atmel/atstk1000/ltv350qv.h | 95 +++++++++++++++++++++++ 3 files changed, 253 insertions(+), 0 deletions(-) create mode 100644 board/atmel/atstk1000/ltv350qv.c create mode 100644 board/atmel/atstk1000/ltv350qv.h diff --git a/board/atmel/atstk1000/Makefile b/board/atmel/atstk1000/Makefile index f9b26e5..8d4f32c 100644 --- a/board/atmel/atstk1000/Makefile +++ b/board/atmel/atstk1000/Makefile @@ -28,6 +28,7 @@ LIB := $(obj)lib$(BOARD).a COBJS-y += $(BOARD).o COBJS-y += flash.o +COBJS-$(CONFIG_LCD) += ltv350qv.o SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) diff --git a/board/atmel/atstk1000/ltv350qv.c b/board/atmel/atstk1000/ltv350qv.c new file mode 100644 index 0000000..5ea6793 --- /dev/null +++ b/board/atmel/atstk1000/ltv350qv.c @@ -0,0 +1,157 @@ +/* + * Power control for Samsung LTV350QV Quarter VGA LCD Panel + * + * Copyright (C) 2006, 2007 Atmel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <common.h> +#include <lcd.h> +#include <spi.h> + +#include "ltv350qv.h" + +/* + * The power-on and power-off sequences are taken from the + * LTV350QV-F04 data sheet from Samsung. The register definitions are + * taken from the S6F2002 command list also from Samsung. Both + * documents are distributed with the AVR32 Linux BSP CD from Atmel. + * + * There's still some voodoo going on here, but it's a lot better than + * in the first incarnation of the driver where all we had was the raw + * numbers from the initialization sequence. + */ +static int ltv350qv_write_reg(struct spi_slave *spi, u8 reg, u16 val) +{ + int ret; + u8 buffer[3]; + + /* register index */ + buffer[0] = LTV_OPC_INDEX; + buffer[1] = 0x00; + buffer[2] = reg & 0x7f; + + ret = spi_xfer_single(spi, 8 * 3, buffer, NULL); + if (ret) + return ret; + + /* register value */ + buffer[0] = LTV_OPC_DATA; + buffer[1] = val >> 8; + buffer[2] = val; + + return spi_xfer_single(spi, 8 * 3, buffer, NULL); +} + +/* The comments are taken straight from the data sheet */ +static int ltv350qv_power_on(struct spi_slave *spi) +{ + int ret; + + spi_claim_bus(spi); + + /* Power On Reset Display off State */ + if (ltv350qv_write_reg(spi, LTV_PWRCTL1, 0x0000)) + goto err; + udelay(15000); + + /* Power Setting Function 1 */ + if (ltv350qv_write_reg(spi, LTV_PWRCTL1, LTV_VCOM_DISABLE)) + goto err; + if (ltv350qv_write_reg(spi, LTV_PWRCTL2, LTV_VCOML_ENABLE)) + goto err_power1; + + /* Power Setting Function 2 */ + if (ltv350qv_write_reg(spi, LTV_PWRCTL1, + LTV_VCOM_DISABLE | LTV_DRIVE_CURRENT(5) + | LTV_SUPPLY_CURRENT(5))) + goto err_power2; + + udelay(55000); + + /* Instruction Setting */ + ret = ltv350qv_write_reg(spi, LTV_IFCTL, + LTV_NMD | LTV_REV | LTV_NL(0x1d)); + ret |= ltv350qv_write_reg(spi, LTV_DATACTL, + LTV_DS_SAME | LTV_CHS_480 + | LTV_DF_RGB | LTV_RGB_BGR); + ret |= ltv350qv_write_reg(spi, LTV_ENTRY_MODE, + LTV_VSPL_ACTIVE_LOW + | LTV_HSPL_ACTIVE_LOW + | LTV_DPL_SAMPLE_RISING + | LTV_EPL_ACTIVE_LOW + | LTV_SS_RIGHT_TO_LEFT); + ret |= ltv350qv_write_reg(spi, LTV_GATECTL1, LTV_CLW(3)); + ret |= ltv350qv_write_reg(spi, LTV_GATECTL2, + LTV_NW_INV_1LINE | LTV_FWI(3)); + ret |= ltv350qv_write_reg(spi, LTV_VBP, 0x000a); + ret |= ltv350qv_write_reg(spi, LTV_HBP, 0x0021); + ret |= ltv350qv_write_reg(spi, LTV_SOTCTL, LTV_SDT(3) | LTV_EQ(0)); + ret |= ltv350qv_write_reg(spi, LTV_GAMMA(0), 0x0103); + ret |= ltv350qv_write_reg(spi, LTV_GAMMA(1), 0x0301); + ret |= ltv350qv_write_reg(spi, LTV_GAMMA(2), 0x1f0f); + ret |= ltv350qv_write_reg(spi, LTV_GAMMA(3), 0x1f0f); + ret |= ltv350qv_write_reg(spi, LTV_GAMMA(4), 0x0707); + ret |= ltv350qv_write_reg(spi, LTV_GAMMA(5), 0x0307); + ret |= ltv350qv_write_reg(spi, LTV_GAMMA(6), 0x0707); + ret |= ltv350qv_write_reg(spi, LTV_GAMMA(7), 0x0000); + ret |= ltv350qv_write_reg(spi, LTV_GAMMA(8), 0x0004); + ret |= ltv350qv_write_reg(spi, LTV_GAMMA(9), 0x0000); + if (ret) + goto err_settings; + + /* Wait more than 2 frames */ + udelay(20000); + + /* Display On Sequence */ + ret = ltv350qv_write_reg(spi, LTV_PWRCTL1, + LTV_VCOM_DISABLE | LTV_VCOMOUT_ENABLE + | LTV_POWER_ON | LTV_DRIVE_CURRENT(5) + | LTV_SUPPLY_CURRENT(5)); + ret |= ltv350qv_write_reg(spi, LTV_GATECTL2, + LTV_NW_INV_1LINE | LTV_DSC | LTV_FWI(3)); + if (ret) + goto err_disp_on; + + /* Display should now be ON. Phew. */ + spi_release_bus(spi); + return 0; + +err_disp_on: + /* + * Try to recover. Error handling probably isn't very useful + * at this point, just make a best effort to switch the panel + * off. + */ + ltv350qv_write_reg(spi, LTV_PWRCTL1, + LTV_VCOM_DISABLE | LTV_DRIVE_CURRENT(5) + | LTV_SUPPLY_CURRENT(5)); + ltv350qv_write_reg(spi, LTV_GATECTL2, + LTV_NW_INV_1LINE | LTV_FWI(3)); +err_settings: +err_power2: +err_power1: + ltv350qv_write_reg(spi, LTV_PWRCTL2, 0x0000); + udelay(1000); +err: + ltv350qv_write_reg(spi, LTV_PWRCTL1, LTV_VCOM_DISABLE); + spi_release_bus(spi); + return -1; +} + +void lcd_enable(void) +{ + struct spi_slave *spi; + int ret = -1; + + spi = spi_setup_slave(0, CFG_LCD_NPCS, 800000, SPI_MODE_3); + if (spi) { + ret = ltv350qv_power_on(spi); + spi_free_slave(spi); + } + + if (ret) + puts("ATSTK1000: Failed to power on LCD panel\n"); +} diff --git a/board/atmel/atstk1000/ltv350qv.h b/board/atmel/atstk1000/ltv350qv.h new file mode 100644 index 0000000..189112e --- /dev/null +++ b/board/atmel/atstk1000/ltv350qv.h @@ -0,0 +1,95 @@ +/* + * Register definitions for Samsung LTV350QV Quarter VGA LCD Panel + * + * Copyright (C) 2006, 2007 Atmel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __LTV350QV_H +#define __LTV350QV_H + +#define LTV_OPC_INDEX 0x74 +#define LTV_OPC_DATA 0x76 + +#define LTV_ID 0x00 /* ID Read */ +#define LTV_IFCTL 0x01 /* Display Interface Control */ +#define LTV_DATACTL 0x02 /* Display Data Control */ +#define LTV_ENTRY_MODE 0x03 /* Entry Mode */ +#define LTV_GATECTL1 0x04 /* Gate Control 1 */ +#define LTV_GATECTL2 0x05 /* Gate Control 2 */ +#define LTV_VBP 0x06 /* Vertical Back Porch */ +#define LTV_HBP 0x07 /* Horizontal Back Porch */ +#define LTV_SOTCTL 0x08 /* Source Output Timing Control */ +#define LTV_PWRCTL1 0x09 /* Power Control 1 */ +#define LTV_PWRCTL2 0x0a /* Power Control 2 */ +#define LTV_GAMMA(x) (0x10 + (x)) /* Gamma control */ + +/* Bit definitions for LTV_IFCTL */ +#define LTV_IM (1 << 15) +#define LTV_NMD (1 << 14) +#define LTV_SSMD (1 << 13) +#define LTV_REV (1 << 7) +#define LTV_NL(x) (((x) & 0x001f) << 0) + +/* Bit definitions for LTV_DATACTL */ +#define LTV_DS_SAME (0 << 12) +#define LTV_DS_D_TO_S (1 << 12) +#define LTV_DS_S_TO_D (2 << 12) +#define LTV_CHS_384 (0 << 9) +#define LTV_CHS_480 (1 << 9) +#define LTV_CHS_492 (2 << 9) +#define LTV_DF_RGB (0 << 6) +#define LTV_DF_RGBX (1 << 6) +#define LTV_DF_XRGB (2 << 6) +#define LTV_RGB_RGB (0 << 2) +#define LTV_RGB_BGR (1 << 2) +#define LTV_RGB_GRB (2 << 2) +#define LTV_RGB_RBG (3 << 2) + +/* Bit definitions for LTV_ENTRY_MODE */ +#define LTV_VSPL_ACTIVE_LOW (0 << 15) +#define LTV_VSPL_ACTIVE_HIGH (1 << 15) +#define LTV_HSPL_ACTIVE_LOW (0 << 14) +#define LTV_HSPL_ACTIVE_HIGH (1 << 14) +#define LTV_DPL_SAMPLE_RISING (0 << 13) +#define LTV_DPL_SAMPLE_FALLING (1 << 13) +#define LTV_EPL_ACTIVE_LOW (0 << 12) +#define LTV_EPL_ACTIVE_HIGH (1 << 12) +#define LTV_SS_LEFT_TO_RIGHT (0 << 8) +#define LTV_SS_RIGHT_TO_LEFT (1 << 8) +#define LTV_STB (1 << 1) + +/* Bit definitions for LTV_GATECTL1 */ +#define LTV_CLW(x) (((x) & 0x0007) << 12) +#define LTV_GAON (1 << 5) +#define LTV_SDR (1 << 3) + +/* Bit definitions for LTV_GATECTL2 */ +#define LTV_NW_INV_FRAME (0 << 14) +#define LTV_NW_INV_1LINE (1 << 14) +#define LTV_NW_INV_2LINE (2 << 14) +#define LTV_DSC (1 << 12) +#define LTV_GIF (1 << 8) +#define LTV_FHN (1 << 7) +#define LTV_FTI(x) (((x) & 0x0003) << 4) +#define LTV_FWI(x) (((x) & 0x0003) << 0) + +/* Bit definitions for LTV_SOTCTL */ +#define LTV_SDT(x) (((x) & 0x0007) << 10) +#define LTV_EQ(x) (((x) & 0x0007) << 2) + +/* Bit definitions for LTV_PWRCTL1 */ +#define LTV_VCOM_DISABLE (1 << 14) +#define LTV_VCOMOUT_ENABLE (1 << 11) +#define LTV_POWER_ON (1 << 9) +#define LTV_DRIVE_CURRENT(x) (((x) & 0x0007) << 4) /* 0=off, 5=max */ +#define LTV_SUPPLY_CURRENT(x) (((x) & 0x0007) << 0) /* 0=off, 5=max */ + +/* Bit definitions for LTV_PWRCTL2 */ +#define LTV_VCOML_ENABLE (1 << 13) +#define LTV_VCOML_VOLTAGE(x) (((x) & 0x001f) << 8) /* 0=1V, 31=-1V */ +#define LTV_VCOMH_VOLTAGE(x) (((x) & 0x001f) << 0) /* 0=3V, 31=4.5V */ + +#endif /* __LTV350QV_H */ -- 1.5.6.3 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot