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

Reply via email to