diff options
author | sl47.kim <sl47.kim@samsung.com> | 2010-12-09 10:20:50 -0800 |
---|---|---|
committer | Arve Hjønnevåg <arve@android.com> | 2011-11-17 17:52:30 -0800 |
commit | 0b1dc139438dc3fb3e7350f5b11b0db2e18bde00 (patch) | |
tree | 43daf85c78ab9ebdcef448f2512517f1258e54b6 | |
parent | 162c33a3c50be30a3747be30f37da95811e59a40 (diff) | |
download | kernel_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/Kconfig | 9 | ||||
-rw-r--r-- | drivers/video/samsung/Makefile | 1 | ||||
-rwxr-xr-x | drivers/video/samsung/s3cfb_nt35580.c | 273 | ||||
-rwxr-xr-x | include/linux/nt35580.h | 26 |
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; +}; + + |