diff --git a/arch/arm/mach-s3c2410/devs.c b/arch/arm/mach-s3c2410/devs.c
index 9a2a67b..c2a3163 100644
--- a/arch/arm/mach-s3c2410/devs.c
+++ b/arch/arm/mach-s3c2410/devs.c
@@ -30,6 +30,7 @@ #include <asm/irq.h>
 #include <asm/arch/regs-serial.h>
 #include <asm/arch/udc.h>
 #include <asm/arch/ts.h>
+#include <asm/arch/lcd.h>
 
 #include "devs.h"
 #include "cpu.h"
@@ -187,6 +188,22 @@ void __init s3c24xx_fb_set_platdata(stru
 	}
 }
 
+struct platform_device s3c_device_bl = {
+	.name		  = "s3c2410-bl",
+	.id		  = -1,
+};
+
+EXPORT_SYMBOL(s3c_device_bl);
+
+static struct s3c2410_bl_mach_info s3c2410bl_info;
+
+void __init set_s3c2410bl_info(struct s3c2410_bl_mach_info *hard_s3c2410bl_info)
+{
+	memcpy(&s3c2410bl_info,hard_s3c2410bl_info,sizeof(struct s3c2410_bl_mach_info));
+	s3c_device_bl.dev.platform_data = &s3c2410bl_info;
+}
+EXPORT_SYMBOL(set_s3c2410bl_info);
+
 /* NAND Controller */
 
 static struct resource s3c_nand_resource[] = {
diff --git a/arch/arm/mach-s3c2410/devs.h b/arch/arm/mach-s3c2410/devs.h
index 0fc63cf..57cea9a 100644
--- a/arch/arm/mach-s3c2410/devs.h
+++ b/arch/arm/mach-s3c2410/devs.h
@@ -23,6 +23,7 @@ extern struct platform_device *s3c24xx_u
 
 extern struct platform_device s3c_device_usb;
 extern struct platform_device s3c_device_lcd;
+extern struct platform_device s3c_device_bl;
 extern struct platform_device s3c_device_wdt;
 extern struct platform_device s3c_device_i2c;
 extern struct platform_device s3c_device_iis;
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index d9a10b5..9c8f219 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -33,12 +33,14 @@ #include <asm/mach-types.h>
 #include <asm/arch/regs-serial.h>
 #include <asm/arch/regs-lcd.h>
 #include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-timer.h>
 #include <asm/arch/regs-clock.h>
 
 #include <asm/arch/h1940-latch.h>
 #include <asm/arch/fb.h>
 #include <asm/arch/udc.h>
 #include <asm/arch/ts.h>
+#include <asm/arch/lcd.h>
 
 #include <linux/serial_core.h>
 
@@ -140,6 +142,21 @@ static struct s3c2410_ts_mach_info h1940
 /**
  * Set lcd on or off
  **/
+
+static void h1940_backlight_power(int on)
+{
+	s3c2410_gpio_setpin(S3C2410_GPB0, 0);
+	s3c2410_gpio_pullup(S3C2410_GPB0, 0);
+
+	s3c2410_gpio_cfgpin(S3C2410_GPB0,
+			    (on) ? S3C2410_GPB0_TOUT0 : S3C2410_GPB0_OUTP);
+}
+
+static void h1940_lcd_power(int on)
+{
+	s3c2410_gpio_setpin(S3C2410_GPC0, on);
+}
+
 static struct s3c2410fb_mach_info h1940_lcdcfg __initdata = {
 	.fixed_syncs=		1,
 	.regs={
@@ -180,9 +197,57 @@ static struct s3c2410fb_mach_info h1940_
 	.bpp=		{16,16,16},
 };
 
+static void h1940_set_brightness(int tcmpb0)
+{
+	unsigned long tcfg0;
+	unsigned long tcfg1;
+	unsigned long tcon;
+
+	/* configure power on/off */
+	h1940_backlight_power(tcmpb0 ? 1 : 0);
+
+
+	tcfg0=readl(S3C2410_TCFG0);
+	tcfg1=readl(S3C2410_TCFG1);
+
+	tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
+	tcfg0 |= 0x18;
+
+	tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK;
+	tcfg1 |= S3C2410_TCFG1_MUX0_DIV2;
+
+	writel(tcfg0, S3C2410_TCFG0);
+	writel(tcfg1, S3C2410_TCFG1);
+	writel(0x31, S3C2410_TCNTB(0));
+
+	tcon = readl(S3C2410_TCON);
+	tcon &= ~0x0F;
+	tcon |= S3C2410_TCON_T0RELOAD;
+	tcon |= S3C2410_TCON_T0MANUALUPD;
+
+	writel(tcon, S3C2410_TCON);
+	writel(0x31, S3C2410_TCNTB(0));
+	writel(tcmpb0, S3C2410_TCMPB(0));
+
+	/* start the timer running */
+	tcon |= S3C2410_TCON_T0START;
+	tcon &= ~S3C2410_TCON_T0MANUALUPD;
+	writel(tcon, S3C2410_TCON);
+}
+
+static struct s3c2410_bl_mach_info h1940_blcfg __initdata = {
+
+	.backlight_max          = 0x2c,
+	.backlight_default      = 0x16,
+	.backlight_power	= h1940_backlight_power,
+	.set_brightness		= h1940_set_brightness,
+	.lcd_power		= h1940_lcd_power
+};
+
 static struct platform_device *h1940_devices[] __initdata = {
 	&s3c_device_usb,
 	&s3c_device_lcd,
+	&s3c_device_bl,
 	&s3c_device_wdt,
 	&s3c_device_i2c,
 	&s3c_device_iis,
@@ -214,6 +279,7 @@ static void __init h1940_init(void)
 
 	s3c24xx_fb_set_platdata(&h1940_lcdcfg);
 	set_s3c2410ts_info(&h1940_ts_cfg);
+	set_s3c2410bl_info(&h1940_blcfg);
  	s3c24xx_udc_set_platdata(&h1940_udc_cfg);
 
 	/* Turn off suspend on both USB ports, and switch the
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 02f1529..f90a003 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -50,6 +50,14 @@ config BACKLIGHT_CORGI
 	  If you have a Sharp Zaurus SL-C7xx, SL-Cxx00 or SL-6000x say y to enable the
 	  backlight driver.
 
+config BACKLIGHT_S3C2410
+	tristate "Samsung S3C2410 Backlight Driver"
+	depends on (BACKLIGHT_DEVICE || LCD_DEVICE) && ARCH_S3C2410
+	default y
+	help
+	  If you have a backlight controler connected on a Samsung S3C2410,
+	  say y here to enable the driver.
+
 config BACKLIGHT_LOCOMO
 	tristate "Sharp LOCOMO LCD/Backlight Driver"
 	depends on BACKLIGHT_DEVICE && SHARP_LOCOMO
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 65e5553..61dfa49 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -3,5 +3,6 @@ # Backlight & LCD drivers
 obj-$(CONFIG_LCD_CLASS_DEVICE)     += lcd.o
 obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
 obj-$(CONFIG_BACKLIGHT_CORGI)	+= corgi_bl.o
+obj-$(CONFIG_BACKLIGHT_S3C2410)	+= s3c2410_lcd.o
 obj-$(CONFIG_BACKLIGHT_HP680)	+= hp680_bl.o
 obj-$(CONFIG_BACKLIGHT_LOCOMO)	+= locomolcd.o
diff --git a/drivers/video/backlight/s3c2410_lcd.c b/drivers/video/backlight/s3c2410_lcd.c
new file mode 100644
index 0000000..ce2929b
--- /dev/null
+++ b/drivers/video/backlight/s3c2410_lcd.c
@@ -0,0 +1,291 @@
+/*
+ * linux/drivers/video/backlight/s3c2410_lcd.c
+ * Copyright (c) Arnaud Patard <arnaud.patard@rtp-net.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ *	    S3C2410 LCD Controller Backlight Driver
+ *
+ * ChangeLog
+ *
+ * 2005-04-07: Arnaud Patard <arnaud.patard@rtp-net.org>
+ *   - Renamed to s3c2410_lcd.c as it include also lcd power controls
+ *
+ * 2005-03-17: Arnaud Patard <arnaud.patard@rtp-net.org>
+ *   - First version
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+#include <linux/backlight.h>
+#endif
+#ifdef CONFIG_LCD_CLASS_DEVICE
+#include <linux/lcd.h>
+#endif
+#include <asm/arch/lcd.h>
+#include <asm/arch/regs-gpio.h>
+
+struct s3c2410bl_devs {
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	struct backlight_device *bl;
+#endif
+#ifdef CONFIG_LCD_CLASS_DEVICE
+	struct lcd_device	*lcd;
+#endif
+};
+
+#ifdef CONFIG_LCD_CLASS_DEVICE
+static int s3c2410bl_get_lcd_power(struct lcd_device *lcd)
+{
+	struct s3c2410_bl_mach_info *info;
+
+	info = (struct s3c2410_bl_mach_info *)class_get_devdata(&lcd->class_dev);
+
+	if (info)
+		return info->lcd_power_value;
+
+	return 0;
+}
+
+static int s3c2410bl_set_lcd_power(struct lcd_device *lcd, int power)
+{
+	struct s3c2410_bl_mach_info *info;
+
+	info = (struct s3c2410_bl_mach_info *)class_get_devdata(&lcd->class_dev);
+
+	if (info && info->lcd_power) {
+		info->lcd_power_value=power;
+		switch(power) {
+			case FB_BLANK_NORMAL:
+			case FB_BLANK_POWERDOWN:
+				info->lcd_power(0);
+				break;
+			default:
+			case FB_BLANK_VSYNC_SUSPEND:
+			case FB_BLANK_HSYNC_SUSPEND:
+			case FB_BLANK_UNBLANK:
+				info->lcd_power(1);
+				break;
+		}
+	}
+
+	return 0;
+}
+#endif
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+static int s3c2410bl_get_bl_brightness(struct backlight_device *bl)
+{
+	struct s3c2410_bl_mach_info *info;
+
+	info = (struct s3c2410_bl_mach_info *)class_get_devdata(&bl->class_dev);
+
+	if(info)
+		return info->brightness_value;
+
+	return 0;
+}
+
+static int s3c2410bl_set_bl_brightness(struct backlight_device *bl)
+{
+	struct s3c2410_bl_mach_info *info;
+	int brightness = bl->props->brightness;
+	int power = bl->props->power;
+
+	info = (struct s3c2410_bl_mach_info *)class_get_devdata(&bl->class_dev);
+
+	if (power != FB_BLANK_UNBLANK)
+		power = 0;
+	else if (bl->props->fb_blank != FB_BLANK_UNBLANK)
+		power = 0;
+	else
+		power = 1;
+
+	if (info && info->set_brightness) {
+		if ( brightness )
+		{
+			info->brightness_value=brightness;
+			info->set_brightness(brightness);
+		}
+		else
+			power = 0;
+	}
+	if (info && info->backlight_power) {
+		info->backlight_power_value=power;
+		info->backlight_power(power);
+	}
+
+	return 0;
+}
+#endif
+
+static int is_s3c2410fb(struct fb_info *info)
+{
+	return (!strcmp(info->fix.id,"s3c2410fb"));
+}
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+static struct backlight_properties s3c2410bl_props = {
+	.get_brightness = s3c2410bl_get_bl_brightness,
+	.update_status	= s3c2410bl_set_bl_brightness,
+	.check_fb 	= is_s3c2410fb
+};
+#endif
+#ifdef CONFIG_LCD_CLASS_DEVICE
+static struct lcd_properties s3c2410lcd_props = {
+	.owner		= THIS_MODULE,
+	.get_power	= s3c2410bl_get_lcd_power,
+	.set_power	= s3c2410bl_set_lcd_power,
+	.check_fb	= is_s3c2410fb
+};
+#endif
+
+static int __init s3c2410bl_probe(struct platform_device *pdev)
+{
+	struct s3c2410bl_devs *devs;
+	struct s3c2410_bl_mach_info *info;
+
+	info = ( struct s3c2410_bl_mach_info *)pdev->dev.platform_data;
+
+
+	devs = (struct s3c2410bl_devs *)kmalloc(sizeof(*devs),GFP_KERNEL);
+	if (!devs) {
+		return -ENOMEM;
+	}
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	devs->bl = backlight_device_register ("s3c2410-bl",info, &s3c2410bl_props);
+
+	if (IS_ERR (devs->bl)) {
+		kfree(devs);
+		return PTR_ERR (devs->bl);
+	}
+
+	/* Register the backlight device */
+	if (!info) {
+		printk(KERN_ERR "Hm... too bad : no platform data for bl\n");
+	}
+	else {
+		s3c2410bl_props.max_brightness = info->backlight_max;
+	}
+
+	/* Set default brightness */
+	devs->bl->props->power = FB_BLANK_UNBLANK;
+	s3c2410bl_props.brightness = info->backlight_default;
+	s3c2410bl_set_bl_brightness(devs->bl);
+#endif
+#ifdef CONFIG_LCD_CLASS_DEVICE
+	devs->lcd = lcd_device_register("s3c2410-lcd",info,&s3c2410lcd_props);
+
+	if (IS_ERR (devs->lcd)) {
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+		backlight_device_unregister(devs->bl);
+#endif
+		kfree(devs);
+		return PTR_ERR (devs->lcd);
+	}
+#endif
+	platform_set_drvdata(pdev, devs);
+
+	printk(KERN_ERR "s3c2410 Backlight Driver Initialized.\n");
+	return 0;
+}
+
+static int s3c2410bl_remove(struct platform_device *pdev)
+{
+	struct s3c2410bl_devs *devs = platform_get_drvdata(pdev);
+
+	if (devs) {
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+		if (devs->bl) {
+			s3c2410bl_props.power = FB_BLANK_POWERDOWN;
+			s3c2410bl_set_bl_brightness(devs->bl);
+			backlight_device_unregister(devs->bl);
+		}
+#endif
+#ifdef CONFIG_LCD_CLASS_DEVICE
+		if (devs->lcd) {
+			lcd_device_unregister(devs->lcd);
+		}
+#endif
+		kfree(devs);
+	}
+	
+	printk("s3c2410 Backlight Driver Unloaded\n");
+
+	return 0;
+
+}
+
+#ifdef CONFIG_PM
+static int s3c2410bl_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct s3c2410bl_devs *devs = platform_get_drvdata(pdev);
+	struct s3c2410_bl_mach_info *info = (struct s3c2410_bl_mach_info *)pdev->dev.platform_data;
+
+	if (devs) {
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+		if (info && info->backlight_power)
+			info->backlight_power(devs->bl->props->power);
+#endif
+#ifdef CONFIG_LCD_CLASS_DEVICE
+		s3c2410bl_set_lcd_power(devs->lcd,0);
+#endif
+	}
+
+	return 0;
+}
+
+static int s3c2410bl_resume(struct platform_device *pdev)
+{
+	struct s3c2410bl_devs *devs = platform_get_drvdata(pdev);
+	struct s3c2410_bl_mach_info *info = (struct s3c2410_bl_mach_info *)pdev->dev.platform_data;
+
+	if (devs) {
+#ifdef CONFIG_LCD_CLASS_DEVICE
+		s3c2410bl_set_lcd_power(devs->lcd,info->lcd_power_value);
+#endif
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+		s3c2410bl_set_bl_brightness(devs->bl);
+#endif
+	}
+	return 0;
+}
+#else
+#define s3c2410bl_suspend NULL
+#define s3c2410bl_resume  NULL
+#endif
+
+static struct platform_driver s3c2410bl_driver = {
+	.driver		= {
+		.name	= "s3c2410-bl",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= s3c2410bl_probe,
+	.remove		= s3c2410bl_remove,
+	.suspend        = s3c2410bl_suspend,
+	.resume         = s3c2410bl_resume,
+};
+
+
+
+static int __init s3c2410bl_init(void)
+{
+	return platform_driver_register(&s3c2410bl_driver);
+}
+
+static void __exit s3c2410bl_cleanup(void)
+{
+	platform_driver_unregister(&s3c2410bl_driver);
+}
+
+module_init(s3c2410bl_init);
+module_exit(s3c2410bl_cleanup);
+
+MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
+MODULE_DESCRIPTION("s3c2410 Backlight Driver");
+MODULE_LICENSE("GPLv2");
+
diff --git a/include/asm-arm/arch-s3c2410/lcd.h b/include/asm-arm/arch-s3c2410/lcd.h
new file mode 100644
index 0000000..0efef0b
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/lcd.h
@@ -0,0 +1,33 @@
+/* linux/include/asm/arch-s3c2410/lcd.h
+ *
+ * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.org>
+ *
+ *
+ * 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.
+ *
+ *
+ *  Changelog:
+ *     14-Mar-2005     RTP     Created file
+ *     07-Apr-2005     RTP     Renamed to s3c2410_lcd.h
+ *     03-Aug-2005     RTP     Renamed to lcd.h
+ */
+
+#ifndef __ASM_ARM_LCD_H
+#define __ASM_ARM_LCD_H
+
+struct s3c2410_bl_mach_info {
+	int		lcd_power_value;
+	int		backlight_power_value;
+	int		brightness_value;
+	int             backlight_max;
+	int             backlight_default;
+	void            (*backlight_power)(int);
+	void            (*set_brightness)(int);
+	void		(*lcd_power)(int);
+};
+
+void __init set_s3c2410bl_info(struct s3c2410_bl_mach_info *hard_s3c2410bl_info);
+
+#endif /* __ASM_ARM_LCD_H */
