[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