[U-Boot] [PATCH 5/6] ATSTK1000: Add driver for the onboard LCD panel
Haavard Skinnemoen
haavard.skinnemoen at atmel.com
Tue Sep 2 11:20:53 CEST 2008
From: Haavard Skinnemoen <hskinnemoen at atmel.com>
This adds mode definitions and initialization code for the on-board
Samsung LTV350QV panel.
Signed-off-by: Haavard Skinnemoen <hskinnemoen at atmel.com>
---
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
More information about the U-Boot
mailing list