
#
# Patch managed by http://www.holgerschurig.de/patcher.html
#

--- /dev/null
+++ linux-2.6.10-rc2/arch/arm/mach-pxa/corgi_backlight.c
@@ -0,0 +1,283 @@
+/*
+ *  Backlight Driver for Sharp Corgi
+ *
+ *  Copyright (c) 2004 Richard Purdie
+ *
+ *  Based on Sharp's 2.4.x Backlight 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/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/pm.h>
+#include <linux/fb.h>
+
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include <asm/arch-pxa/corgi.h>
+
+extern unsigned short set_scoop_gpio(unsigned short bit);
+extern unsigned short reset_scoop_gpio(unsigned short bit);
+extern void corgi_ssp_blduty_set(int duty);
+
+#define CORGI_LIGHT_SETTING 7     // range setting : 0(OFF) dim 1 2 3 4 5(MAX)
+#define CORGI_LIGHT_DEFAULT 6
+#define SetBacklightVR(a)	if (a) {set_scoop_gpio(CORGI_SCP_BACKLIGHT_CONT);} else {reset_scoop_gpio(CORGI_SCP_BACKLIGHT_CONT);}
+
+static int is_corgibl_blank = 0;
+int counter_step_contrast = CORGI_LIGHT_DEFAULT;
+static int corgibl_limit = CORGI_LIGHT_SETTING - 1;
+static int counter_step_save     = 0;
+static int corgibl_step_contrast_setting(int);
+static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED;
+
+typedef struct _duty_vr_t {
+	int duty;
+	int vr;
+} duty_vr_t;
+
+static duty_vr_t corgibl_duty_table[CORGI_LIGHT_SETTING] = {
+	{0x00, 0},	//   0%		Light Off
+	{0x01, 0},	//  20%		Dim 1
+	{0x05, 0},	//  40%		2
+	{0x0b, 0},	//  70%		3
+	{0x05, 1},	//  40%		4
+	{0x0b, 1},	//  70%		5
+	{0x1f, 1}	// 100%		6
+};
+
+void corgibl_blank(int blank)
+{
+	if (blank && !is_corgibl_blank) {
+		is_corgibl_blank = 1;
+		counter_step_save = counter_step_contrast;
+		corgibl_step_contrast_setting(0);
+	} else if (!blank && is_corgibl_blank) {
+		corgibl_step_contrast_setting(counter_step_save);
+		is_corgibl_blank = 0;
+	}
+}
+
+/*
+int corgibl_power(int state)
+{
+	if (state) corgibl_blank(0);
+	else corgibl_blank(1);
+
+	return 0;
+}*/
+
+#ifdef CONFIG_PM
+static int corgibl_suspend(struct device *dev, u32 state, u32 level)
+{
+	corgibl_blank(1);
+	return 0;
+}
+
+static int corgibl_resume(struct device *dev, u32 level)
+{
+	corgibl_blank(0);
+	return 0;
+}
+#else
+#define corgibl_suspend	NULL
+#define corgibl_resume	NULL
+#endif
+
+
+static int corgibl_step_contrast_setting(int need_value)
+{
+	unsigned long flags;
+	extern void sharpsl_kick_battery_check(int,int,int);
+
+	//sharpsl_kick_battery_check(0,1,0);	/* check battery and wait 10msec */
+
+	if (need_value < 0 ) need_value = 0;
+	if ( need_value > corgibl_limit )
+		need_value = corgibl_limit;
+
+	spin_lock_irqsave(&bl_lock, flags);
+	corgi_ssp_blduty_set(corgibl_duty_table[need_value].duty);
+	SetBacklightVR(corgibl_duty_table[need_value].vr);
+	spin_unlock_irqrestore(&bl_lock, flags);
+	counter_step_contrast = need_value;
+
+	//sharpsl_kick_battery_check(1,0,0);	/* wait 10msec and check battery */
+
+	return counter_step_contrast;
+}
+
+/*
+#define CORGI_BL_RESET_CONTRAST		(-1)
+#define CORGI_BL_CAUTION_CONTRAST	(3)
+
+static int corgibl_step_contrast_setting_nocheck(int need_value)
+{
+	unsigned long flags;
+
+	if (need_value < 0 ) need_value = 0;
+	if ( need_value > corgibl_limit )
+		need_value = corgibl_limit;
+
+	spin_lock_irqsave(&bl_lock, flags);
+	corgi_ssp_blduty_set(corgibl_duty_table[need_value].duty);
+	SetBacklightVR(corgibl_duty_table[need_value].vr);
+	spin_unlock_irqrestore(&bl_lock, flags);
+
+	counter_step_contrast = need_value;
+
+	return counter_step_contrast;
+}
+
+void corgibl_set_limit_contrast(int val)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&bl_lock, flags);
+	if ((val > CORGI_LIGHT_SETTING - 1) || (val < 0)) {
+		if (corgibl_limit != CORGI_LIGHT_SETTING - 1) {
+			printk("corgi_bl : unlimit contrast\n");
+		}
+		corgibl_limit = CORGI_LIGHT_SETTING - 1;
+	}
+	else {
+		if (corgibl_limit != val) {
+			printk("corgi_bl : change limit contrast %d\n", val);
+		}
+		corgibl_limit = val;
+	}
+	spin_unlock_irqrestore(&bl_lock, flags);
+	if (counter_step_contrast > corgibl_limit) {
+		corgibl_step_contrast_setting_nocheck(corgibl_limit);
+	}
+} */
+
+
+/*	switch(cmd) {
+	case CORGI_BL_IOCTL_ON:
+		ret = corgibl_step_contrast_setting(counter_step_contrast);
+		break;
+	case CORGI_BL_IOCTL_OFF:
+		ret = corgibl_step_contrast_setting(0);
+		break;
+	case CORGI_BL_IOCTL_STEP_CONTRAST:
+		ret = corgibl_step_contrast_setting(arg);
+		break;
+	case CORGI_BL_IOCTL_GET_STEP_CONTRAST:
+		ret = counter_step_contrast;
+		break;
+	case CORGI_BL_IOCTL_GET_STEP:
+		ret = CORGI_LIGHT_SETTING;
+		break;
+	default:
+		;
+	}*/
+
+static struct device_driver corgibl_driver;
+
+static ssize_t corgibl_intensity_read(struct device *dev, char *buf)
+{
+        return scnprintf(buf, PAGE_SIZE, "0x%02X%02X\n",
+					corgibl_duty_table[counter_step_contrast].vr,
+					corgibl_duty_table[counter_step_contrast].duty );
+}
+static ssize_t corgibl_intensity_store(struct device *dev,
+				      const char *buf, size_t count)
+{
+	unsigned long param;
+	if ((count > 0) && (1 == sscanf(buf, "%lx", &param)) ) {
+			corgi_ssp_blduty_set(param & 0xff);
+			SetBacklightVR((param & 0xff00) >> 8);
+		return count;
+	}
+	return -EINVAL;
+}
+
+static int corgibl_event_notify(struct notifier_block *self, 
+			      unsigned long action, void *data)
+{
+	struct fb_event *event = data;
+	struct fb_info *info = event->info;
+	
+	switch(action) {
+	case FB_EVENT_BLANK:
+		switch(*(int *)(event->data)) {
+
+		case FB_BLANK_NORMAL: 
+		case FB_BLANK_VSYNC_SUSPEND:
+		case FB_BLANK_HSYNC_SUSPEND:
+		case FB_BLANK_POWERDOWN: 
+  			corgibl_blank(1);
+  			break;
+ 	
+		case FB_BLANK_UNBLANK: 
+   			corgibl_blank(0);
+	  		break;
+ 		}
+	}
+	return 0;
+}
+
+static DEVICE_ATTR(intensity, 0644, corgibl_intensity_read, corgibl_intensity_store);
+
+static struct notifier_block corgibl_event_notifier = {
+	.notifier_call	= corgibl_event_notify,
+};
+
+int __init corgibl_probe(struct device *dev)
+{
+	device_create_file(dev,&dev_attr_intensity);
+
+	corgibl_step_contrast_setting(counter_step_contrast);
+	
+	fb_register_client(&corgibl_event_notifier);
+
+	printk("Corgi Backlight Driver Initialized.\n");
+	return 0;
+}
+
+static int corgibl_remove(struct device *dev)
+{
+	corgibl_step_contrast_setting(0);
+
+	driver_remove_file(&corgibl_driver,&dev_attr_intensity);
+	
+	printk("Backlight Driver Unloaded\n");
+	return 0;
+}
+
+static struct device_driver corgibl_driver = {
+	.name		= "corgi-bl",
+	.bus		= &platform_bus_type,
+	.probe		= corgibl_probe,
+	.remove		= corgibl_remove,
+	.suspend	= corgibl_suspend,
+	.resume		= corgibl_resume,
+};
+
+int __init corgibl_init(void)
+{
+	return driver_register(&corgibl_driver);
+}
+
+void __exit corgibl_exit(void)
+{
+ 	driver_unregister(&corgibl_driver);
+}
+
+module_init(corgibl_init);
+module_exit(corgibl_exit);

