aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsl47.kim <sl47.kim@samsung.com>2010-12-09 10:20:50 -0800
committerArve Hjønnevåg <arve@android.com>2011-11-17 17:52:30 -0800
commit0b1dc139438dc3fb3e7350f5b11b0db2e18bde00 (patch)
tree43daf85c78ab9ebdcef448f2512517f1258e54b6
parent162c33a3c50be30a3747be30f37da95811e59a40 (diff)
downloadkernel_samsung_crespo-0b1dc139438dc3fb3e7350f5b11b0db2e18bde00.zip
kernel_samsung_crespo-0b1dc139438dc3fb3e7350f5b11b0db2e18bde00.tar.gz
kernel_samsung_crespo-0b1dc139438dc3fb3e7350f5b11b0db2e18bde00.tar.bz2
S5PC11X: LCD: Add new lcd driver to support the TFT LCD
Add nt35580 lcd driver to support the TFT LCD version Change-Id: I5939042ffe4e47ebc5133e1084c6d2f4db377f70 Signed-off-by: sl47.kim <sl47.kim@samsung.com>
-rwxr-xr-x[-rw-r--r--]drivers/video/samsung/Kconfig9
-rw-r--r--drivers/video/samsung/Makefile1
-rwxr-xr-xdrivers/video/samsung/s3cfb_nt35580.c273
-rwxr-xr-xinclude/linux/nt35580.h26
4 files changed, 309 insertions, 0 deletions
diff --git a/drivers/video/samsung/Kconfig b/drivers/video/samsung/Kconfig
index 0f0b5f5..f0d9511 100644..100755
--- a/drivers/video/samsung/Kconfig
+++ b/drivers/video/samsung/Kconfig
@@ -94,6 +94,15 @@ config FB_S3C_TL2796
---help---
This enables support for Samsung TL2796 WVGA LCD panel
+config FB_S3C_NT35580
+ bool "NT35580"
+ depends on FB_S3C
+ select SPI
+ select SPI_GPIO
+ select SPI_BITBANG
+ ---help---
+ This enables support for SONY NT35580 WVGA LCD panel
+
config FB_S3C_LVDS
bool "LVDS"
depends on FB_S3C && (ARCH_S5PV210)
diff --git a/drivers/video/samsung/Makefile b/drivers/video/samsung/Makefile
index e317c86..d4f5271 100644
--- a/drivers/video/samsung/Makefile
+++ b/drivers/video/samsung/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_FB_S3C_LTE480WV) += s3cfb_lte480wv.o
obj-$(CONFIG_FB_S3C_LVDS) += s3cfb_lvds.o
obj-$(CONFIG_FB_S3C_HT101HD1) += s3cfb_ht101hd1.o
obj-$(CONFIG_FB_S3C_TL2796) += s3cfb_tl2796.o
+obj-$(CONFIG_FB_S3C_NT35580) += s3cfb_nt35580.o
obj-$(CONFIG_FB_S3C_AMS701KA) += s3cfb_ams701ka.o
obj-$(CONFIG_FB_S3C_MDNIE) += s3cfb_mdnie.o s3cfb_ielcd.o
obj-$(CONFIG_FB_S3C_CMC623) += tune_cmc623.o
diff --git a/drivers/video/samsung/s3cfb_nt35580.c b/drivers/video/samsung/s3cfb_nt35580.c
new file mode 100755
index 0000000..aad5b32
--- /dev/null
+++ b/drivers/video/samsung/s3cfb_nt35580.c
@@ -0,0 +1,273 @@
+/*
+ * nt35580 TFT Panel Driver for the Samsung Universal board
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/wait.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/lcd.h>
+#include <linux/backlight.h>
+#include <linux/nt35580.h>
+#include <plat/gpio-cfg.h>
+#include <plat/regs-fb.h>
+#include <linux/earlysuspend.h>
+
+#define PWM_REG_OFFSET 1
+#define NT35580_POWERON_DELAY 150
+
+struct s5p_lcd {
+ int ldi_enable;
+ int bl;
+ struct mutex lock;
+ struct device *dev;
+ struct spi_device *g_spi;
+ struct s5p_tft_panel_data *data;
+ struct backlight_device *bl_dev;
+ struct early_suspend early_suspend;
+};
+
+static int nt35580_spi_write_driver(struct s5p_lcd *lcd, u16 reg)
+{
+ u16 buf;
+ int ret;
+ struct spi_message msg;
+
+ struct spi_transfer xfer = {
+ .len = 2,
+ .tx_buf = &buf,
+ };
+
+ buf = reg;
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer, &msg);
+
+ ret = spi_sync(lcd->g_spi, &msg);
+
+ if (ret < 0)
+ pr_err("%s: error: spi_sync (%d)", __func__, ret);
+
+ return ret;
+}
+
+static void nt35580_panel_send_sequence(struct s5p_lcd *lcd,
+ const u16 *wbuf)
+{
+ int i = 0;
+
+ while ((wbuf[i] & DEFMASK) != ENDDEF)
+ if ((wbuf[i] & DEFMASK) != SLEEPMSEC) {
+ nt35580_spi_write_driver(lcd, wbuf[i]);
+ i += 1;
+ } else {
+ msleep(wbuf[i+1]);
+ i += 2;
+ }
+}
+
+static void update_brightness(struct s5p_lcd *lcd, int level)
+{
+ struct s5p_tft_panel_data *pdata = lcd->data;
+
+ pdata->brightness_set[PWM_REG_OFFSET] = 0x100 | (level & 0xff);
+
+ nt35580_panel_send_sequence(lcd, pdata->brightness_set);
+}
+
+static void nt35580_ldi_enable(struct s5p_lcd *lcd)
+{
+ struct s5p_tft_panel_data *pdata = lcd->data;
+
+ mutex_lock(&lcd->lock);
+
+ msleep(NT35580_POWERON_DELAY);
+
+ nt35580_panel_send_sequence(lcd, pdata->seq_set);
+ update_brightness(lcd, lcd->bl);
+ nt35580_panel_send_sequence(lcd, pdata->display_on);
+
+ lcd->ldi_enable = 1;
+
+ mutex_unlock(&lcd->lock);
+}
+
+static void nt35580_ldi_disable(struct s5p_lcd *lcd)
+{
+ struct s5p_tft_panel_data *pdata = lcd->data;
+
+ mutex_lock(&lcd->lock);
+
+ lcd->ldi_enable = 0;
+ nt35580_panel_send_sequence(lcd, pdata->display_off);
+ nt35580_panel_send_sequence(lcd, pdata->sleep_in);
+
+ mutex_unlock(&lcd->lock);
+}
+
+static int s5p_bl_update_status(struct backlight_device *bd)
+{
+ struct s5p_lcd *lcd = bl_get_data(bd);
+ int bl = bd->props.brightness;
+
+ pr_debug("\nupdate status brightness %d\n",
+ bd->props.brightness);
+
+ if (bl < 0 || bl > 255)
+ return -EINVAL;
+
+ mutex_lock(&lcd->lock);
+
+ lcd->bl = bl;
+
+ if (lcd->ldi_enable) {
+ pr_debug("\n bl :%d\n", bl);
+ update_brightness(lcd, bl);
+ }
+
+ mutex_unlock(&lcd->lock);
+
+ return 0;
+}
+
+const struct backlight_ops s5p_bl_tft_ops = {
+ .update_status = s5p_bl_update_status,
+};
+
+void nt35580_early_suspend(struct early_suspend *h)
+{
+ struct s5p_lcd *lcd = container_of(h, struct s5p_lcd,
+ early_suspend);
+
+ nt35580_ldi_disable(lcd);
+
+ return;
+}
+void nt35580_late_resume(struct early_suspend *h)
+{
+ struct s5p_lcd *lcd = container_of(h, struct s5p_lcd,
+ early_suspend);
+
+ nt35580_ldi_enable(lcd);
+
+ return;
+}
+static int __devinit nt35580_probe(struct spi_device *spi)
+{
+ struct s5p_lcd *lcd;
+ int ret;
+
+ lcd = kzalloc(sizeof(*lcd), GFP_KERNEL);
+ if (!lcd) {
+ pr_err("failed to allocate for lcd\n");
+ ret = -ENOMEM;
+ goto err_alloc;
+ }
+ mutex_init(&lcd->lock);
+
+ spi->bits_per_word = 9;
+ if (spi_setup(spi)) {
+ pr_err("failed to setup spi\n");
+ ret = -EINVAL;
+ goto err_setup;
+ }
+
+ lcd->g_spi = spi;
+ lcd->dev = &spi->dev;
+ lcd->bl = 255;
+
+ if (!spi->dev.platform_data) {
+ dev_err(lcd->dev, "failed to get platform data\n");
+ ret = -EINVAL;
+ goto err_setup;
+ }
+ lcd->data = (struct s5p_tft_panel_data *)spi->dev.platform_data;
+
+ if (!lcd->data->seq_set || !lcd->data->display_on ||
+ !lcd->data->display_off || !lcd->data->sleep_in ||
+ !lcd->data->brightness_set) {
+ dev_err(lcd->dev, "Invalid platform data\n");
+ ret = -EINVAL;
+ goto err_setup;
+ }
+
+ lcd->bl_dev = backlight_device_register("s5p_bl",
+ &spi->dev, lcd, &s5p_bl_tft_ops, NULL);
+ if (!lcd->bl_dev) {
+ dev_err(lcd->dev, "failed to register backlight\n");
+ ret = -EINVAL;
+ goto err_setup;
+ }
+
+ lcd->bl_dev->props.max_brightness = 255;
+ spi_set_drvdata(spi, lcd);
+
+ nt35580_ldi_enable(lcd);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ lcd->early_suspend.suspend = nt35580_early_suspend;
+ lcd->early_suspend.resume = nt35580_late_resume;
+ lcd->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1;
+ register_early_suspend(&lcd->early_suspend);
+#endif
+ pr_info("%s successfully probed\n", __func__);
+
+ return 0;
+
+err_setup:
+ mutex_destroy(&lcd->lock);
+ kfree(lcd);
+
+err_alloc:
+ return ret;
+}
+
+static int __devexit nt35580_remove(struct spi_device *spi)
+{
+ struct s5p_lcd *lcd = spi_get_drvdata(spi);
+
+ unregister_early_suspend(&lcd->early_suspend);
+
+ backlight_device_unregister(lcd->bl_dev);
+
+ nt35580_ldi_disable(lcd);
+
+ kfree(lcd);
+
+ return 0;
+}
+
+static struct spi_driver nt35580_driver = {
+ .driver = {
+ .name = "nt35580",
+ .owner = THIS_MODULE,
+ },
+ .probe = nt35580_probe,
+ .remove = __devexit_p(nt35580_remove),
+};
+
+static int __init nt35580_init(void)
+{
+ return spi_register_driver(&nt35580_driver);
+}
+static void __exit nt35580_exit(void)
+{
+ spi_unregister_driver(&nt35580_driver);
+}
+
+module_init(nt35580_init);
+module_exit(nt35580_exit);
diff --git a/include/linux/nt35580.h b/include/linux/nt35580.h
new file mode 100755
index 0000000..2791cfa
--- /dev/null
+++ b/include/linux/nt35580.h
@@ -0,0 +1,26 @@
+/*include/linux/nt35580.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Header file for Sony LCD Panel(TFT) driver
+ *
+ * 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 <linux/types.h>
+
+#define SLEEPMSEC 0x1000
+#define ENDDEF 0x2000
+#define DEFMASK 0xFF00
+
+struct s5p_tft_panel_data {
+ const u16 *seq_set;
+ const u16 *sleep_in;
+ const u16 *display_on;
+ const u16 *display_off;
+ u16 *brightness_set;
+};
+
+