diff --git a/MAINTAINERS b/MAINTAINERS
index 6261597a1bce..6fc033f22751 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -679,6 +679,11 @@ L:	linux-hams@vger.kernel.org
 W:	http://www.linux-ax25.org/
 S:	Maintained
 
+BACKLIGHT CLASS/SUBSYSTEM
+P:	Richard Purdie
+M:	rpurdie@rpsys.net
+S:	Maintained
+
 BAYCOM/HDLCDRV DRIVERS FOR AX.25
 P:	Thomas Sailer
 M:	t.sailer@alumni.ethz.ch
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index dcc6f159fd94..17724fb2067f 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -107,12 +107,10 @@ int die(const char *str, struct pt_regs *regs, long err)
 	if (machine_is(powermac) && pmac_backlight) {
 		struct backlight_properties *props;
 
-		down(&pmac_backlight->sem);
-		props = pmac_backlight->props;
+		props = &pmac_backlight->props;
 		props->brightness = props->max_brightness;
 		props->power = FB_BLANK_UNBLANK;
-		props->update_status(pmac_backlight);
-		up(&pmac_backlight->sem);
+		backlight_update_status(pmac_backlight);
 	}
 	mutex_unlock(&pmac_backlight_mutex);
 #endif
diff --git a/arch/powerpc/platforms/powermac/backlight.c b/arch/powerpc/platforms/powermac/backlight.c
index c3a89414ddc0..de7440e62cc4 100644
--- a/arch/powerpc/platforms/powermac/backlight.c
+++ b/arch/powerpc/platforms/powermac/backlight.c
@@ -37,21 +37,20 @@ static int pmac_backlight_set_legacy_queued;
  */
 static atomic_t kernel_backlight_disabled = ATOMIC_INIT(0);
 
-/* Protect the pmac_backlight variable */
+/* Protect the pmac_backlight variable below.
+   You should hold this lock when using the pmac_backlight pointer to
+   prevent its potential removal. */
 DEFINE_MUTEX(pmac_backlight_mutex);
 
 /* Main backlight storage
  *
- * Backlight drivers in this variable are required to have the "props"
+ * Backlight drivers in this variable are required to have the "ops"
  * attribute set and to have an update_status function.
  *
  * We can only store one backlight here, but since Apple laptops have only one
  * internal display, it doesn't matter. Other backlight drivers can be used
  * independently.
  *
- * Lock ordering:
- * pmac_backlight_mutex (global, main backlight)
- *   pmac_backlight->sem (backlight class)
  */
 struct backlight_device *pmac_backlight;
 
@@ -104,8 +103,7 @@ static void pmac_backlight_key_worker(struct work_struct *work)
 		struct backlight_properties *props;
 		int brightness;
 
-		down(&pmac_backlight->sem);
-		props = pmac_backlight->props;
+		props = &pmac_backlight->props;
 
 		brightness = props->brightness +
 			((pmac_backlight_key_queued?-1:1) *
@@ -117,9 +115,7 @@ static void pmac_backlight_key_worker(struct work_struct *work)
 			brightness = props->max_brightness;
 
 		props->brightness = brightness;
-		props->update_status(pmac_backlight);
-
-		up(&pmac_backlight->sem);
+		backlight_update_status(pmac_backlight);
 	}
 	mutex_unlock(&pmac_backlight_mutex);
 }
@@ -145,8 +141,7 @@ static int __pmac_backlight_set_legacy_brightness(int brightness)
 	if (pmac_backlight) {
 		struct backlight_properties *props;
 
-		down(&pmac_backlight->sem);
-		props = pmac_backlight->props;
+		props = &pmac_backlight->props;
 		props->brightness = brightness *
 			(props->max_brightness + 1) /
 			(OLD_BACKLIGHT_MAX + 1);
@@ -156,8 +151,7 @@ static int __pmac_backlight_set_legacy_brightness(int brightness)
 		else if (props->brightness < 0)
 			props->brightness = 0;
 
-		props->update_status(pmac_backlight);
-		up(&pmac_backlight->sem);
+		backlight_update_status(pmac_backlight);
 
 		error = 0;
 	}
@@ -196,14 +190,11 @@ int pmac_backlight_get_legacy_brightness()
 	if (pmac_backlight) {
 		struct backlight_properties *props;
 
-		down(&pmac_backlight->sem);
-		props = pmac_backlight->props;
+		props = &pmac_backlight->props;
 
 		result = props->brightness *
 			(OLD_BACKLIGHT_MAX + 1) /
 			(props->max_brightness + 1);
-
-		up(&pmac_backlight->sem);
 	}
 	mutex_unlock(&pmac_backlight_mutex);
 
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
index 772299fb5f9d..b770deab968c 100644
--- a/drivers/acpi/asus_acpi.c
+++ b/drivers/acpi/asus_acpi.c
@@ -848,7 +848,7 @@ out:
 
 static int set_brightness_status(struct backlight_device *bd)
 {
-	return set_brightness(bd->props->brightness);
+	return set_brightness(bd->props.brightness);
 }
 
 static int
@@ -1352,11 +1352,9 @@ static int asus_hotk_remove(struct acpi_device *device, int type)
 	return 0;
 }
 
-static struct backlight_properties asus_backlight_data = {
-        .owner          = THIS_MODULE,
+static struct backlight_ops asus_backlight_data = {
         .get_brightness = read_brightness,
         .update_status  = set_brightness_status,
-        .max_brightness = 15,
 };
 
 static void __exit asus_acpi_exit(void)
@@ -1410,6 +1408,7 @@ static int __init asus_acpi_init(void)
 		asus_backlight_device = NULL;
 		asus_acpi_exit();
 	}
+        asus_backlight_device->props.max_brightness = 15;
 
 	return 0;
 }
diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c
index 1a0ed3dc409c..4cc534e36e81 100644
--- a/drivers/acpi/ibm_acpi.c
+++ b/drivers/acpi/ibm_acpi.c
@@ -1701,14 +1701,12 @@ static int brightness_write(char *buf)
 
 static int brightness_update_status(struct backlight_device *bd)
 {
-	return brightness_set(bd->props->brightness);
+	return brightness_set(bd->props.brightness);
 }
 
-static struct backlight_properties ibm_backlight_data = {
-        .owner          = THIS_MODULE,
+static struct backlight_ops ibm_backlight_data = {
         .get_brightness = brightness_get,
         .update_status  = brightness_update_status,
-        .max_brightness = 7,
 };
 
 static int brightness_init(void)
@@ -1720,6 +1718,8 @@ static int brightness_init(void)
 		return PTR_ERR(ibm_backlight_device);
 	}
 
+        ibm_backlight_device->props.max_brightness = 7;
+
 	return 0;
 }
 
diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c
index faf8a5232d8e..3906d47b9783 100644
--- a/drivers/acpi/toshiba_acpi.c
+++ b/drivers/acpi/toshiba_acpi.c
@@ -315,7 +315,7 @@ static int set_lcd(int value)
 
 static int set_lcd_status(struct backlight_device *bd)
 {
-	return set_lcd(bd->props->brightness);
+	return set_lcd(bd->props.brightness);
 }
 
 static unsigned long write_lcd(const char *buffer, unsigned long count)
@@ -533,11 +533,9 @@ static acpi_status __exit remove_device(void)
 	return AE_OK;
 }
 
-static struct backlight_properties toshiba_backlight_data = {
-        .owner          = THIS_MODULE,
+static struct backlight_ops toshiba_backlight_data = {
         .get_brightness = get_lcd,
         .update_status  = set_lcd_status,
-        .max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1,
 };
 
 static void __exit toshiba_acpi_exit(void)
@@ -597,6 +595,7 @@ static int __init toshiba_acpi_init(void)
 		toshiba_backlight_device = NULL;
 		toshiba_acpi_exit();
 	}
+        toshiba_backlight_device->props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
 
 	return (ACPI_SUCCESS(status)) ? 0 : -ENODEV;
 }
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index bf525cca3b63..0771b434feb2 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -169,7 +169,6 @@ struct acpi_video_device {
 	struct acpi_device *dev;
 	struct acpi_video_device_brightness *brightness;
 	struct backlight_device *backlight;
-	struct backlight_properties *data;
 };
 
 /* bus */
@@ -286,13 +285,18 @@ static int acpi_video_get_brightness(struct backlight_device *bd)
 
 static int acpi_video_set_brightness(struct backlight_device *bd)
 {
-	int request_level = bd->props->brightness;
+	int request_level = bd->props.brightness;
 	struct acpi_video_device *vd =
 		(struct acpi_video_device *)class_get_devdata(&bd->class_dev);
 	acpi_video_device_lcd_set_level(vd, request_level);
 	return 0;
 }
 
+static struct backlight_ops acpi_backlight_ops = {
+	.get_brightness = acpi_video_get_brightness,
+	.update_status  = acpi_video_set_brightness,
+};
+
 /* --------------------------------------------------------------------------
                                Video Management
    -------------------------------------------------------------------------- */
@@ -608,31 +612,18 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
 		unsigned long tmp;
 		static int count = 0;
 		char *name;
-		struct backlight_properties *acpi_video_data;
-
 		name = kzalloc(MAX_NAME_LEN, GFP_KERNEL);
 		if (!name)
 			return;
 
-		acpi_video_data = kzalloc(
-			sizeof(struct backlight_properties),
-			GFP_KERNEL);
-		if (!acpi_video_data){
-			kfree(name);
-			return;
-		}
-		acpi_video_data->owner = THIS_MODULE;
-		acpi_video_data->get_brightness =
-			acpi_video_get_brightness;
-		acpi_video_data->update_status =
-			acpi_video_set_brightness;
 		sprintf(name, "acpi_video%d", count++);
-		device->data = acpi_video_data;
-		acpi_video_data->max_brightness = max_level;
 		acpi_video_device_lcd_get_level_current(device, &tmp);
-		acpi_video_data->brightness = (int)tmp;
 		device->backlight = backlight_device_register(name,
-			NULL, device, acpi_video_data);
+			NULL, device, &acpi_backlight_ops);
+		device->backlight->props.max_brightness = max_level;
+		device->backlight->props.brightness = (int)tmp;
+		backlight_update_status(device->backlight);
+
 		kfree(name);
 	}
 	return;
@@ -1677,10 +1668,7 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
 	status = acpi_remove_notify_handler(device->dev->handle,
 					    ACPI_DEVICE_NOTIFY,
 					    acpi_video_device_notify);
-	if (device->backlight){
-		backlight_device_unregister(device->backlight);
-		kfree(device->data);
-	}
+	backlight_device_unregister(device->backlight);
 	return 0;
 }
 
diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c
index 801a974342f9..7e27071746e4 100644
--- a/drivers/macintosh/via-pmu-backlight.c
+++ b/drivers/macintosh/via-pmu-backlight.c
@@ -15,7 +15,7 @@
 
 #define MAX_PMU_LEVEL 0xFF
 
-static struct backlight_properties pmu_backlight_data;
+static struct backlight_ops pmu_backlight_data;
 static DEFINE_SPINLOCK(pmu_backlight_lock);
 static int sleeping;
 static u8 bl_curve[FB_BACKLIGHT_LEVELS];
@@ -72,7 +72,7 @@ static int pmu_backlight_update_status(struct backlight_device *bd)
 {
 	struct adb_request req;
 	unsigned long flags;
-	int level = bd->props->brightness;
+	int level = bd->props.brightness;
 
 	spin_lock_irqsave(&pmu_backlight_lock, flags);
 
@@ -80,8 +80,8 @@ static int pmu_backlight_update_status(struct backlight_device *bd)
 	if (sleeping)
 		goto out;
 
-	if (bd->props->power != FB_BLANK_UNBLANK ||
-	    bd->props->fb_blank != FB_BLANK_UNBLANK)
+	if (bd->props.power != FB_BLANK_UNBLANK ||
+	    bd->props.fb_blank != FB_BLANK_UNBLANK)
 		level = 0;
 
 	if (level > 0) {
@@ -107,14 +107,13 @@ out:
 
 static int pmu_backlight_get_brightness(struct backlight_device *bd)
 {
-	return bd->props->brightness;
+	return bd->props.brightness;
 }
 
-static struct backlight_properties pmu_backlight_data = {
-	.owner		= THIS_MODULE,
+static struct backlight_ops pmu_backlight_data = {
 	.get_brightness	= pmu_backlight_get_brightness,
 	.update_status	= pmu_backlight_update_status,
-	.max_brightness	= (FB_BACKLIGHT_LEVELS - 1),
+
 };
 
 #ifdef CONFIG_PM
@@ -152,9 +151,10 @@ void __init pmu_backlight_init()
 		printk("pmubl: Backlight registration failed\n");
 		goto error;
 	}
+	bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
 	pmu_backlight_init_curve(0x7F, 0x46, 0x0E);
 
-	level = pmu_backlight_data.max_brightness;
+	level = bd->props.max_brightness;
 
 	if (autosave) {
 		/* read autosaved value if available */
@@ -164,19 +164,12 @@ void __init pmu_backlight_init()
 
 		level = pmu_backlight_curve_lookup(
 				(req.reply[0] >> 4) *
-				pmu_backlight_data.max_brightness / 15);
+				bd->props.max_brightness / 15);
 	}
 
-	down(&bd->sem);
-	bd->props->brightness = level;
-	bd->props->power = FB_BLANK_UNBLANK;
-	bd->props->update_status(bd);
-	up(&bd->sem);
-
-	mutex_lock(&pmac_backlight_mutex);
-	if (!pmac_backlight)
-		pmac_backlight = bd;
-	mutex_unlock(&pmac_backlight_mutex);
+	bd->props.brightness = level;
+	bd->props.power = FB_BLANK_UNBLANK;
+	backlight_update_status(bd);
 
 	printk("pmubl: Backlight initialized (%s)\n", name);
 
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c
index e4e2b707a353..295e931c0dfb 100644
--- a/drivers/misc/asus-laptop.c
+++ b/drivers/misc/asus-laptop.c
@@ -195,11 +195,9 @@ static struct backlight_device *asus_backlight_device;
  */
 static int read_brightness(struct backlight_device *bd);
 static int update_bl_status(struct backlight_device *bd);
-static struct backlight_properties asusbl_data = {
-	.owner = THIS_MODULE,
+static struct backlight_ops asusbl_ops = {
 	.get_brightness = read_brightness,
 	.update_status = update_bl_status,
-	.max_brightness = 15,
 };
 
 /* These functions actually update the LED's, and are called from a
@@ -349,13 +347,8 @@ static void lcd_blank(int blank)
 	struct backlight_device *bd = asus_backlight_device;
 
 	if (bd) {
-		down(&bd->sem);
-		if (likely(bd->props)) {
-			bd->props->power = blank;
-			if (likely(bd->props->update_status))
-				bd->props->update_status(bd);
-		}
-		up(&bd->sem);
+		bd->props.power = blank;
+		backlight_update_status(bd);
 	}
 }
 
@@ -387,13 +380,13 @@ static int set_brightness(struct backlight_device *bd, int value)
 static int update_bl_status(struct backlight_device *bd)
 {
 	int rv;
-	int value = bd->props->brightness;
+	int value = bd->props.brightness;
 
 	rv = set_brightness(bd, value);
 	if (rv)
 		return rv;
 
-	value = (bd->props->power == FB_BLANK_UNBLANK) ? 1 : 0;
+	value = (bd->props.power == FB_BLANK_UNBLANK) ? 1 : 0;
 	return set_lcd_state(value);
 }
 
@@ -1019,7 +1012,7 @@ static int asus_backlight_init(struct device *dev)
 
 	if (brightness_set_handle && lcd_switch_handle) {
 		bd = backlight_device_register(ASUS_HOTK_FILE, dev,
-					       NULL, &asusbl_data);
+					       NULL, &asusbl_ops);
 		if (IS_ERR(bd)) {
 			printk(ASUS_ERR
 			       "Could not register asus backlight device\n");
@@ -1029,14 +1022,10 @@ static int asus_backlight_init(struct device *dev)
 
 		asus_backlight_device = bd;
 
-		down(&bd->sem);
-		if (likely(bd->props)) {
-			bd->props->brightness = read_brightness(NULL);
-			bd->props->power = FB_BLANK_UNBLANK;
-			if (likely(bd->props->update_status))
-				bd->props->update_status(bd);
-		}
-		up(&bd->sem);
+		bd->props.max_brightness = 15;
+		bd->props.brightness = read_brightness(NULL);
+		bd->props.power = FB_BLANK_UNBLANK;
+		backlight_update_status(bd);
 	}
 	return 0;
 }
diff --git a/drivers/misc/msi-laptop.c b/drivers/misc/msi-laptop.c
index 8e5e07e4c1cf..68c4b58525ba 100644
--- a/drivers/misc/msi-laptop.c
+++ b/drivers/misc/msi-laptop.c
@@ -157,14 +157,12 @@ static int bl_get_brightness(struct backlight_device *b)
 
 static int bl_update_status(struct backlight_device *b)
 {
-	return set_lcd_level(b->props->brightness);
+	return set_lcd_level(b->props.brightness);
 }
 
-static struct backlight_properties msibl_props = {
-	.owner		= THIS_MODULE,
+static struct backlight_ops msibl_ops = {
 	.get_brightness = bl_get_brightness,
 	.update_status  = bl_update_status,
-	.max_brightness = MSI_LCD_LEVEL_MAX-1,
 };
 
 static struct backlight_device *msibl_device;
@@ -318,10 +316,12 @@ static int __init msi_init(void)
 	/* Register backlight stuff */
 
 	msibl_device = backlight_device_register("msi-laptop-bl", NULL, NULL,
-						&msibl_props);
+						&msibl_ops);
 	if (IS_ERR(msibl_device))
 		return PTR_ERR(msibl_device);
 
+	msibl_device->props.max_brightness = MSI_LCD_LEVEL_MAX-1,
+
 	ret = platform_driver_register(&msipf_driver);
 	if (ret)
 		goto fail_backlight;
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
index cabbed0015e4..2ebe240dd537 100644
--- a/drivers/misc/sony-laptop.c
+++ b/drivers/misc/sony-laptop.c
@@ -384,7 +384,7 @@ static void sony_snc_pf_remove(void)
 static int sony_backlight_update_status(struct backlight_device *bd)
 {
 	return acpi_callsetfunc(sony_acpi_handle, "SBRT",
-				bd->props->brightness + 1, NULL);
+				bd->props.brightness + 1, NULL);
 }
 
 static int sony_backlight_get_brightness(struct backlight_device *bd)
@@ -398,11 +398,9 @@ static int sony_backlight_get_brightness(struct backlight_device *bd)
 }
 
 static struct backlight_device *sony_backlight_device;
-static struct backlight_properties sony_backlight_properties = {
-	.owner = THIS_MODULE,
+static struct backlight_ops sony_backlight_ops = {
 	.update_status = sony_backlight_update_status,
 	.get_brightness = sony_backlight_get_brightness,
-	.max_brightness = SONY_MAX_BRIGHTNESS - 1,
 };
 
 /*
@@ -484,15 +482,19 @@ static int sony_acpi_add(struct acpi_device *device)
 	if (ACPI_SUCCESS(acpi_get_handle(sony_acpi_handle, "GBRT", &handle))) {
 		sony_backlight_device = backlight_device_register("sony", NULL,
 								  NULL,
-								  &sony_backlight_properties);
+								  &sony_backlight_ops);
 
 		if (IS_ERR(sony_backlight_device)) {
 			printk(LOG_PFX "unable to register backlight device\n");
 			sony_backlight_device = NULL;
-		} else
-			sony_backlight_properties.brightness =
+		} else {
+			sony_backlight_device->props.brightness =
 			    sony_backlight_get_brightness
 			    (sony_backlight_device);
+			sony_backlight_device->props.max_brightness = 
+			    SONY_MAX_BRIGHTNESS - 1;
+		}
+
 	}
 
 	if (sony_snc_pf_add())
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
index e573c8ba9785..cf70c16f0e3f 100644
--- a/drivers/usb/misc/appledisplay.c
+++ b/drivers/usb/misc/appledisplay.c
@@ -141,7 +141,7 @@ static int appledisplay_bl_update_status(struct backlight_device *bd)
 	int retval;
 
 	pdata->msgdata[0] = 0x10;
-	pdata->msgdata[1] = bd->props->brightness;
+	pdata->msgdata[1] = bd->props.brightness;
 
 	retval = usb_control_msg(
 		pdata->udev,
@@ -177,11 +177,9 @@ static int appledisplay_bl_get_brightness(struct backlight_device *bd)
 		return pdata->msgdata[1];
 }
 
-static struct backlight_properties appledisplay_bl_data = {
-	.owner		= THIS_MODULE,
+static struct backlight_ops appledisplay_bl_data = {
 	.get_brightness	= appledisplay_bl_get_brightness,
 	.update_status	= appledisplay_bl_update_status,
-	.max_brightness	= 0xFF
 };
 
 static void appledisplay_work(struct work_struct *work)
@@ -190,11 +188,9 @@ static void appledisplay_work(struct work_struct *work)
 		container_of(work, struct appledisplay, work.work);
 	int retval;
 
-	up(&pdata->bd->sem);
 	retval = appledisplay_bl_get_brightness(pdata->bd);
 	if (retval >= 0)
-		pdata->bd->props->brightness = retval;
-	down(&pdata->bd->sem);
+		pdata->bd->props.brightness = retval;
 
 	/* Poll again in about 125ms if there's still a button pressed */
 	if (pdata->button_pressed)
@@ -288,10 +284,10 @@ static int appledisplay_probe(struct usb_interface *iface,
 		goto error;
 	}
 
+	pdata->bd->props.max_brightness = 0xff;
+
 	/* Try to get brightness */
-	up(&pdata->bd->sem);
 	brightness = appledisplay_bl_get_brightness(pdata->bd);
-	down(&pdata->bd->sem);
 
 	if (brightness < 0) {
 		retval = brightness;
@@ -300,9 +296,7 @@ static int appledisplay_probe(struct usb_interface *iface,
 	}
 
 	/* Set brightness in backlight device */
-	up(&pdata->bd->sem);
-	pdata->bd->props->brightness = brightness;
-	down(&pdata->bd->sem);
+	pdata->bd->props.brightness = brightness;
 
 	/* save our data pointer in the interface device */
 	usb_set_intfdata(iface, pdata);
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 8874cf2fd279..f8bc43c1e7a7 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -4,20 +4,7 @@
 
 menu "Graphics support"
 
-config FIRMWARE_EDID
-       bool "Enable firmware EDID"
-       default y
-       ---help---
-         This enables access to the EDID transferred from the firmware.
-	 On the i386, this is from the Video BIOS. Enable this if DDC/I2C
-	 transfers do not work for your driver and if you are using
-	 nvidiafb, i810fb or savagefb.
-
-	 In general, choosing Y for this option is safe.  If you
-	 experience extremely long delays while booting before you get
-	 something on your display, try setting this to N.  Matrox cards in
-	 combination with certain motherboards and monitors are known to
-	 suffer from this problem.
+source "drivers/video/backlight/Kconfig"
 
 config FB
 	tristate "Support for frame buffer devices"
@@ -53,9 +40,27 @@ config FB
 	  (e.g. an accelerated X server) and that are not frame buffer
 	  device-aware may cause unexpected results. If unsure, say N.
 
+config FIRMWARE_EDID
+       bool "Enable firmware EDID"
+       depends on FB
+       default n
+       ---help---
+         This enables access to the EDID transferred from the firmware.
+	 On the i386, this is from the Video BIOS. Enable this if DDC/I2C
+	 transfers do not work for your driver and if you are using
+	 nvidiafb, i810fb or savagefb.
+
+	 In general, choosing Y for this option is safe.  If you
+	 experience extremely long delays while booting before you get
+	 something on your display, try setting this to N.  Matrox cards in
+	 combination with certain motherboards and monitors are known to
+	 suffer from this problem.
+
 config FB_DDC
        tristate
-       depends on FB && I2C && I2C_ALGOBIT
+       depends on FB
+       select I2C_ALGOBIT
+       select I2C
        default n
 
 config FB_CFB_FILLRECT
@@ -134,6 +139,9 @@ config FB_TILEBLITTING
 	 This is particularly important to one driver, matroxfb.  If
 	 unsure, say N.
 
+comment "Frambuffer hardware drivers"
+	depends on FB
+
 config FB_CIRRUS
 	tristate "Cirrus Logic support"
 	depends on FB && (ZORRO || PCI)
@@ -671,6 +679,7 @@ config FB_NVIDIA
 	depends on FB && PCI
 	select I2C_ALGOBIT if FB_NVIDIA_I2C
 	select I2C if FB_NVIDIA_I2C
+	select FB_BACKLIGHT if FB_NVIDIA_BACKLIGHT
 	select FB_MODE_HELPERS
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
@@ -699,8 +708,7 @@ config FB_NVIDIA_I2C
 
 config FB_NVIDIA_BACKLIGHT
 	bool "Support for backlight control"
-	depends on FB_NVIDIA && PMAC_BACKLIGHT
-	select FB_BACKLIGHT
+	depends on FB_NVIDIA
 	default y
 	help
 	  Say Y here if you want to control the backlight of your display.
@@ -708,9 +716,8 @@ config FB_NVIDIA_BACKLIGHT
 config FB_RIVA
 	tristate "nVidia Riva support"
 	depends on FB && PCI
-	select I2C_ALGOBIT if FB_RIVA_I2C
-	select I2C if FB_RIVA_I2C
 	select FB_DDC if FB_RIVA_I2C
+	select FB_BACKLIGHT if FB_RIVA_BACKLIGHT
 	select FB_MODE_HELPERS
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
@@ -747,8 +754,7 @@ config FB_RIVA_DEBUG
 
 config FB_RIVA_BACKLIGHT
 	bool "Support for backlight control"
-	depends on FB_RIVA && PMAC_BACKLIGHT
-	select FB_BACKLIGHT
+	depends on FB_RIVA
 	default y
 	help
 	  Say Y here if you want to control the backlight of your display.
@@ -798,8 +804,6 @@ config FB_I810_GTF
 config FB_I810_I2C
 	bool "Enable DDC Support"
 	depends on FB_I810 && FB_I810_GTF
-	select I2C
-	select I2C_ALGOBIT
 	select FB_DDC
 	help
 
@@ -989,9 +993,8 @@ config FB_MATROX_MULTIHEAD
 config FB_RADEON
 	tristate "ATI Radeon display support"
 	depends on FB && PCI
-	select I2C_ALGOBIT if FB_RADEON_I2C
-	select I2C if FB_RADEON_I2C
 	select FB_DDC if FB_RADEON_I2C
+	select FB_BACKLIGHT if FB_RADEON_BACKLIGHT
 	select FB_MODE_HELPERS
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
@@ -1021,8 +1024,7 @@ config FB_RADEON_I2C
 
 config FB_RADEON_BACKLIGHT
 	bool "Support for backlight control"
-	depends on FB_RADEON && PMAC_BACKLIGHT
-	select FB_BACKLIGHT
+	depends on FB_RADEON
 	default y
 	help
 	  Say Y here if you want to control the backlight of your display.
@@ -1042,6 +1044,7 @@ config FB_ATY128
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
+	select FB_BACKLIGHT if FB_ATY128_BACKLIGHT
 	select FB_MACMODES if PPC_PMAC
 	help
 	  This driver supports graphics boards with the ATI Rage128 chips.
@@ -1053,8 +1056,7 @@ config FB_ATY128
 
 config FB_ATY128_BACKLIGHT
 	bool "Support for backlight control"
-	depends on FB_ATY128 && PMAC_BACKLIGHT
-	select FB_BACKLIGHT
+	depends on FB_ATY128
 	default y
 	help
 	  Say Y here if you want to control the backlight of your display.
@@ -1065,6 +1067,7 @@ config FB_ATY
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
+	select FB_BACKLIGHT if FB_ATY_BACKLIGHT
 	select FB_MACMODES if PPC
 	help
 	  This driver supports graphics boards with the ATI Mach64 chips.
@@ -1103,8 +1106,7 @@ config FB_ATY_GX
 
 config FB_ATY_BACKLIGHT
 	bool "Support for backlight control"
-	depends on FB_ATY && PMAC_BACKLIGHT
-	select FB_BACKLIGHT
+	depends on FB_ATY
 	default y
 	help
 	  Say Y here if you want to control the backlight of your display.
@@ -1123,8 +1125,6 @@ config FB_S3
 config FB_SAVAGE
 	tristate "S3 Savage support"
 	depends on FB && PCI && EXPERIMENTAL
-	select I2C_ALGOBIT if FB_SAVAGE_I2C
-	select I2C if FB_SAVAGE_I2C
 	select FB_DDC if FB_SAVAGE_I2C
 	select FB_MODE_HELPERS
 	select FB_CFB_FILLRECT
@@ -1639,6 +1639,7 @@ config FB_VIRTUAL
 	  the vfb_enable=1 option.
 
 	  If unsure, say N.
+
 if VT
 	source "drivers/video/console/Kconfig"
 endif
@@ -1647,9 +1648,5 @@ if FB || SGI_NEWPORT_CONSOLE
 	source "drivers/video/logo/Kconfig"
 endif
 
-if SYSFS
-	source "drivers/video/backlight/Kconfig"
-endif
-
 endmenu
 
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 6801edff36d9..1b79a6f13f0c 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -12,7 +12,7 @@ fb-objs                           := $(fb-y)
 
 obj-$(CONFIG_VT)		  += console/
 obj-$(CONFIG_LOGO)		  += logo/
-obj-$(CONFIG_SYSFS)		  += backlight/
+obj-y				  += backlight/
 
 obj-$(CONFIG_FB_CFB_FILLRECT)  += cfbfillrect.o
 obj-$(CONFIG_FB_CFB_COPYAREA)  += cfbcopyarea.o
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index 2e976ffcde0f..8726c3669713 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -1695,9 +1695,6 @@ static int __devinit aty128fb_setup(char *options)
 #ifdef CONFIG_FB_ATY128_BACKLIGHT
 #define MAX_LEVEL 0xFF
 
-static struct backlight_properties aty128_bl_data;
-
-/* Call with fb_info->bl_mutex held */
 static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
 		int level)
 {
@@ -1705,6 +1702,7 @@ static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
 	int atylevel;
 
 	/* Get and convert the value */
+	/* No locking of bl_curve since we read a single value */
 	atylevel = MAX_LEVEL -
 		(info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL);
 
@@ -1724,19 +1722,18 @@ static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
 /* That one prevents proper CRT output with LCD off */
 #undef BACKLIGHT_DAC_OFF
 
-/* Call with fb_info->bl_mutex held */
-static int __aty128_bl_update_status(struct backlight_device *bd)
+static int aty128_bl_update_status(struct backlight_device *bd)
 {
 	struct aty128fb_par *par = class_get_devdata(&bd->class_dev);
 	unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL);
 	int level;
 
-	if (bd->props->power != FB_BLANK_UNBLANK ||
-	    bd->props->fb_blank != FB_BLANK_UNBLANK ||
+	if (bd->props.power != FB_BLANK_UNBLANK ||
+	    bd->props.fb_blank != FB_BLANK_UNBLANK ||
 	    !par->lcd_on)
 		level = 0;
 	else
-		level = bd->props->brightness;
+		level = bd->props.brightness;
 
 	reg |= LVDS_BL_MOD_EN | LVDS_BLON;
 	if (level > 0) {
@@ -1778,43 +1775,22 @@ static int __aty128_bl_update_status(struct backlight_device *bd)
 	return 0;
 }
 
-static int aty128_bl_update_status(struct backlight_device *bd)
-{
-	struct aty128fb_par *par = class_get_devdata(&bd->class_dev);
-	struct fb_info *info = pci_get_drvdata(par->pdev);
-	int ret;
-
-	mutex_lock(&info->bl_mutex);
-	ret = __aty128_bl_update_status(bd);
-	mutex_unlock(&info->bl_mutex);
-
-	return ret;
-}
-
 static int aty128_bl_get_brightness(struct backlight_device *bd)
 {
-	return bd->props->brightness;
+	return bd->props.brightness;
 }
 
-static struct backlight_properties aty128_bl_data = {
-	.owner		= THIS_MODULE,
+static struct backlight_ops aty128_bl_data = {
 	.get_brightness	= aty128_bl_get_brightness,
 	.update_status	= aty128_bl_update_status,
-	.max_brightness	= (FB_BACKLIGHT_LEVELS - 1),
 };
 
 static void aty128_bl_set_power(struct fb_info *info, int power)
 {
-	mutex_lock(&info->bl_mutex);
-
 	if (info->bl_dev) {
-		down(&info->bl_dev->sem);
-		info->bl_dev->props->power = power;
-		__aty128_bl_update_status(info->bl_dev);
-		up(&info->bl_dev->sem);
+		info->bl_dev->props.power = power;
+		backlight_update_status(info->bl_dev);
 	}
-
-	mutex_unlock(&info->bl_mutex);
 }
 
 static void aty128_bl_init(struct aty128fb_par *par)
@@ -1841,25 +1817,15 @@ static void aty128_bl_init(struct aty128fb_par *par)
 		goto error;
 	}
 
-	mutex_lock(&info->bl_mutex);
 	info->bl_dev = bd;
 	fb_bl_default_curve(info, 0,
 		 63 * FB_BACKLIGHT_MAX / MAX_LEVEL,
 		219 * FB_BACKLIGHT_MAX / MAX_LEVEL);
-	mutex_unlock(&info->bl_mutex);
 
-	down(&bd->sem);
-	bd->props->brightness = aty128_bl_data.max_brightness;
-	bd->props->power = FB_BLANK_UNBLANK;
-	bd->props->update_status(bd);
-	up(&bd->sem);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_lock(&pmac_backlight_mutex);
-	if (!pmac_backlight)
-		pmac_backlight = bd;
-	mutex_unlock(&pmac_backlight_mutex);
-#endif
+	bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+	bd->props.brightness = bd->props.max_brightness;
+	bd->props.power = FB_BLANK_UNBLANK;
+	backlight_update_status(bd);
 
 	printk("aty128: Backlight initialized (%s)\n", name);
 
@@ -1869,31 +1835,10 @@ error:
 	return;
 }
 
-static void aty128_bl_exit(struct aty128fb_par *par)
+static void aty128_bl_exit(struct backlight_device *bd)
 {
-	struct fb_info *info = pci_get_drvdata(par->pdev);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_lock(&pmac_backlight_mutex);
-#endif
-
-	mutex_lock(&info->bl_mutex);
-	if (info->bl_dev) {
-#ifdef CONFIG_PMAC_BACKLIGHT
-		if (pmac_backlight == info->bl_dev)
-			pmac_backlight = NULL;
-#endif
-
-		backlight_device_unregister(info->bl_dev);
-		info->bl_dev = NULL;
-
-		printk("aty128: Backlight unloaded\n");
-	}
-	mutex_unlock(&info->bl_mutex);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_unlock(&pmac_backlight_mutex);
-#endif
+	backlight_device_unregister(bd);
+	printk("aty128: Backlight unloaded\n");
 }
 #endif /* CONFIG_FB_ATY128_BACKLIGHT */
 
@@ -2180,11 +2125,12 @@ static void __devexit aty128_remove(struct pci_dev *pdev)
 
 	par = info->par;
 
+	unregister_framebuffer(info);
+
 #ifdef CONFIG_FB_ATY128_BACKLIGHT
-	aty128_bl_exit(par);
+	aty128_bl_exit(info->bl_dev);
 #endif
 
-	unregister_framebuffer(info);
 #ifdef CONFIG_MTRR
 	if (par->mtrr.vram_valid)
 		mtrr_del(par->mtrr.vram, info->fix.smem_start,
@@ -2214,11 +2160,6 @@ static int aty128fb_blank(int blank, struct fb_info *fb)
 	if (par->lock_blank || par->asleep)
 		return 0;
 
-#ifdef CONFIG_FB_ATY128_BACKLIGHT
-	if (machine_is(powermac) && blank)
-		aty128_bl_set_power(fb, FB_BLANK_POWERDOWN);
-#endif
-
 	if (blank & FB_BLANK_VSYNC_SUSPEND)
 		state |= 2;
 	if (blank & FB_BLANK_HSYNC_SUSPEND)
@@ -2233,11 +2174,6 @@ static int aty128fb_blank(int blank, struct fb_info *fb)
 		aty128_set_lcd_enable(par, par->lcd_on && !blank);
 	}
 
-#ifdef CONFIG_FB_ATY128_BACKLIGHT
-	if (machine_is(powermac) && !blank)
-		aty128_bl_set_power(fb, FB_BLANK_UNBLANK);
-#endif
-
 	return 0;
 }
 
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 301612cef354..a7e0062233f2 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -2114,15 +2114,13 @@ static int atyfb_pci_resume(struct pci_dev *pdev)
 #ifdef CONFIG_FB_ATY_BACKLIGHT
 #define MAX_LEVEL 0xFF
 
-static struct backlight_properties aty_bl_data;
-
-/* Call with fb_info->bl_mutex held */
 static int aty_bl_get_level_brightness(struct atyfb_par *par, int level)
 {
 	struct fb_info *info = pci_get_drvdata(par->pdev);
 	int atylevel;
 
 	/* Get and convert the value */
+	/* No locking of bl_curve since we read a single value */
 	atylevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
 
 	if (atylevel < 0)
@@ -2133,18 +2131,17 @@ static int aty_bl_get_level_brightness(struct atyfb_par *par, int level)
 	return atylevel;
 }
 
-/* Call with fb_info->bl_mutex held */
-static int __aty_bl_update_status(struct backlight_device *bd)
+static int aty_bl_update_status(struct backlight_device *bd)
 {
 	struct atyfb_par *par = class_get_devdata(&bd->class_dev);
 	unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par);
 	int level;
 
-	if (bd->props->power != FB_BLANK_UNBLANK ||
-	    bd->props->fb_blank != FB_BLANK_UNBLANK)
+	if (bd->props.power != FB_BLANK_UNBLANK ||
+	    bd->props.fb_blank != FB_BLANK_UNBLANK)
 		level = 0;
 	else
-		level = bd->props->brightness;
+		level = bd->props.brightness;
 
 	reg |= (BLMOD_EN | BIASMOD_EN);
 	if (level > 0) {
@@ -2159,45 +2156,16 @@ static int __aty_bl_update_status(struct backlight_device *bd)
 	return 0;
 }
 
-static int aty_bl_update_status(struct backlight_device *bd)
-{
-	struct atyfb_par *par = class_get_devdata(&bd->class_dev);
-	struct fb_info *info = pci_get_drvdata(par->pdev);
-	int ret;
-
-	mutex_lock(&info->bl_mutex);
-	ret = __aty_bl_update_status(bd);
-	mutex_unlock(&info->bl_mutex);
-
-	return ret;
-}
-
 static int aty_bl_get_brightness(struct backlight_device *bd)
 {
-	return bd->props->brightness;
+	return bd->props.brightness;
 }
 
-static struct backlight_properties aty_bl_data = {
-	.owner	  = THIS_MODULE,
+static struct backlight_ops aty_bl_data = {
 	.get_brightness = aty_bl_get_brightness,
 	.update_status	= aty_bl_update_status,
-	.max_brightness = (FB_BACKLIGHT_LEVELS - 1),
 };
 
-static void aty_bl_set_power(struct fb_info *info, int power)
-{
-	mutex_lock(&info->bl_mutex);
-
-	if (info->bl_dev) {
-		down(&info->bl_dev->sem);
-		info->bl_dev->props->power = power;
-		__aty_bl_update_status(info->bl_dev);
-		up(&info->bl_dev->sem);
-	}
-
-	mutex_unlock(&info->bl_mutex);
-}
-
 static void aty_bl_init(struct atyfb_par *par)
 {
 	struct fb_info *info = pci_get_drvdata(par->pdev);
@@ -2218,25 +2186,15 @@ static void aty_bl_init(struct atyfb_par *par)
 		goto error;
 	}
 
-	mutex_lock(&info->bl_mutex);
 	info->bl_dev = bd;
 	fb_bl_default_curve(info, 0,
 		0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL,
 		0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL);
-	mutex_unlock(&info->bl_mutex);
 
-	down(&bd->sem);
-	bd->props->brightness = aty_bl_data.max_brightness;
-	bd->props->power = FB_BLANK_UNBLANK;
-	bd->props->update_status(bd);
-	up(&bd->sem);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_lock(&pmac_backlight_mutex);
-	if (!pmac_backlight)
-		pmac_backlight = bd;
-	mutex_unlock(&pmac_backlight_mutex);
-#endif
+	bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+	bd->props.brightness = bd->props.max_brightness;
+	bd->props.power = FB_BLANK_UNBLANK;
+	backlight_update_status(bd);
 
 	printk("aty: Backlight initialized (%s)\n", name);
 
@@ -2246,30 +2204,10 @@ error:
 	return;
 }
 
-static void aty_bl_exit(struct atyfb_par *par)
+static void aty_bl_exit(struct backlight_device *bd)
 {
-	struct fb_info *info = pci_get_drvdata(par->pdev);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_lock(&pmac_backlight_mutex);
-#endif
-
-	mutex_lock(&info->bl_mutex);
-	if (info->bl_dev) {
-#ifdef CONFIG_PMAC_BACKLIGHT
-		if (pmac_backlight == info->bl_dev)
-			pmac_backlight = NULL;
-#endif
-
-		backlight_device_unregister(info->bl_dev);
-
-		printk("aty: Backlight unloaded\n");
-	}
-	mutex_unlock(&info->bl_mutex);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_unlock(&pmac_backlight_mutex);
-#endif
+	backlight_device_unregister(bd);
+	printk("aty: Backlight unloaded\n");
 }
 
 #endif /* CONFIG_FB_ATY_BACKLIGHT */
@@ -2814,8 +2752,6 @@ static int atyfb_blank(int blank, struct fb_info *info)
 		return 0;
 
 #ifdef CONFIG_FB_ATY_BACKLIGHT
-	if (machine_is(powermac) && blank > FB_BLANK_NORMAL)
-		aty_bl_set_power(info, FB_BLANK_POWERDOWN);
 #elif defined(CONFIG_FB_ATY_GENERIC_LCD)
 	if (par->lcd_table && blank > FB_BLANK_NORMAL &&
 	    (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
@@ -2846,8 +2782,6 @@ static int atyfb_blank(int blank, struct fb_info *info)
 	aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
 
 #ifdef CONFIG_FB_ATY_BACKLIGHT
-	if (machine_is(powermac) && blank <= FB_BLANK_NORMAL)
-		aty_bl_set_power(info, FB_BLANK_UNBLANK);
 #elif defined(CONFIG_FB_ATY_GENERIC_LCD)
 	if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
 	    (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
@@ -3726,13 +3660,13 @@ static void __devexit atyfb_remove(struct fb_info *info)
 	aty_set_crtc(par, &saved_crtc);
 	par->pll_ops->set_pll(info, &saved_pll);
 
+	unregister_framebuffer(info);
+
 #ifdef CONFIG_FB_ATY_BACKLIGHT
 	if (M64_HAS(MOBIL_BUS))
-		aty_bl_exit(par);
+		aty_bl_exit(info->bl_dev);
 #endif
 
-	unregister_framebuffer(info);
-
 #ifdef CONFIG_MTRR
 	if (par->mtrr_reg >= 0) {
 	    mtrr_del(par->mtrr_reg, 0, 0);
diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c
index 3abfd4a380cc..0be25fa5540c 100644
--- a/drivers/video/aty/radeon_backlight.c
+++ b/drivers/video/aty/radeon_backlight.c
@@ -19,8 +19,6 @@
 
 #define MAX_RADEON_LEVEL 0xFF
 
-static struct backlight_properties radeon_bl_data;
-
 struct radeon_bl_privdata {
 	struct radeonfb_info *rinfo;
 	uint8_t negative;
@@ -29,17 +27,13 @@ struct radeon_bl_privdata {
 static int radeon_bl_get_level_brightness(struct radeon_bl_privdata *pdata,
 		int level)
 {
-	struct fb_info *info = pdata->rinfo->info;
 	int rlevel;
 
-	mutex_lock(&info->bl_mutex);
-
 	/* Get and convert the value */
+	/* No locking of bl_curve since we read a single value */
 	rlevel = pdata->rinfo->info->bl_curve[level] *
 		 FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL;
 
-	mutex_unlock(&info->bl_mutex);
-
 	if (rlevel < 0)
 		rlevel = 0;
 	else if (rlevel > MAX_RADEON_LEVEL)
@@ -65,11 +59,11 @@ static int radeon_bl_update_status(struct backlight_device *bd)
 	 * backlight. This provides some greater power saving and the display
 	 * is useless without backlight anyway.
 	 */
-        if (bd->props->power != FB_BLANK_UNBLANK ||
-	    bd->props->fb_blank != FB_BLANK_UNBLANK)
+        if (bd->props.power != FB_BLANK_UNBLANK ||
+	    bd->props.fb_blank != FB_BLANK_UNBLANK)
 		level = 0;
 	else
-		level = bd->props->brightness;
+		level = bd->props.brightness;
 
 	del_timer_sync(&rinfo->lvds_timer);
 	radeon_engine_idle();
@@ -130,14 +124,12 @@ static int radeon_bl_update_status(struct backlight_device *bd)
 
 static int radeon_bl_get_brightness(struct backlight_device *bd)
 {
-	return bd->props->brightness;
+	return bd->props.brightness;
 }
 
-static struct backlight_properties radeon_bl_data = {
-	.owner		= THIS_MODULE,
+static struct backlight_ops radeon_bl_data = {
 	.get_brightness = radeon_bl_get_brightness,
 	.update_status	= radeon_bl_update_status,
-	.max_brightness = (FB_BACKLIGHT_LEVELS - 1),
 };
 
 void radeonfb_bl_init(struct radeonfb_info *rinfo)
@@ -188,25 +180,15 @@ void radeonfb_bl_init(struct radeonfb_info *rinfo)
 		machine_is_compatible("PowerBook6,5");
 #endif
 
-	mutex_lock(&rinfo->info->bl_mutex);
 	rinfo->info->bl_dev = bd;
 	fb_bl_default_curve(rinfo->info, 0,
 		 63 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL,
 		217 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL);
-	mutex_unlock(&rinfo->info->bl_mutex);
 
-	down(&bd->sem);
-	bd->props->brightness = radeon_bl_data.max_brightness;
-	bd->props->power = FB_BLANK_UNBLANK;
-	bd->props->update_status(bd);
-	up(&bd->sem);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_lock(&pmac_backlight_mutex);
-	if (!pmac_backlight)
-		pmac_backlight = bd;
-	mutex_unlock(&pmac_backlight_mutex);
-#endif
+	bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+	bd->props.brightness = bd->props.max_brightness;
+	bd->props.power = FB_BLANK_UNBLANK;
+	backlight_update_status(bd);
 
 	printk("radeonfb: Backlight initialized (%s)\n", name);
 
@@ -219,29 +201,16 @@ error:
 
 void radeonfb_bl_exit(struct radeonfb_info *rinfo)
 {
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_lock(&pmac_backlight_mutex);
-#endif
+	struct backlight_device *bd = rinfo->info->bl_dev;
 
-	mutex_lock(&rinfo->info->bl_mutex);
-	if (rinfo->info->bl_dev) {
+	if (bd) {
 		struct radeon_bl_privdata *pdata;
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-		if (pmac_backlight == rinfo->info->bl_dev)
-			pmac_backlight = NULL;
-#endif
-
-		pdata = class_get_devdata(&rinfo->info->bl_dev->class_dev);
-		backlight_device_unregister(rinfo->info->bl_dev);
+		pdata = class_get_devdata(&bd->class_dev);
+		backlight_device_unregister(bd);
 		kfree(pdata);
 		rinfo->info->bl_dev = NULL;
 
 		printk("radeonfb: Backlight unloaded\n");
 	}
-	mutex_unlock(&rinfo->info->bl_mutex);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_unlock(&pmac_backlight_mutex);
-#endif
 }
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 0ed577e7cc21..7e228aded4c2 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -2393,7 +2393,6 @@ static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev)
         if (!rinfo)
                 return;
 
-	radeonfb_bl_exit(rinfo);
 	radeonfb_pm_exit(rinfo);
 
 	if (rinfo->mon1_EDID)
@@ -2420,6 +2419,8 @@ static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev)
 
         unregister_framebuffer(info);
 
+        radeonfb_bl_exit(rinfo);
+
         iounmap(rinfo->mmio_base);
         iounmap(rinfo->fb_base);
  
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 02f15297a021..47d15b5d985a 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -19,11 +19,6 @@ config BACKLIGHT_CLASS_DEVICE
 	  To have support for your specific LCD panel you will have to
 	  select the proper drivers which depend on this option.
 
-config BACKLIGHT_DEVICE
-	bool
-	depends on BACKLIGHT_CLASS_DEVICE
-	default y
-
 config LCD_CLASS_DEVICE
         tristate "Lowlevel LCD controls"
 	depends on BACKLIGHT_LCD_SUPPORT
@@ -37,14 +32,9 @@ config LCD_CLASS_DEVICE
 	  To have support for your specific LCD panel you will have to
 	  select the proper drivers which depend on this option.
 
-config LCD_DEVICE
-	bool
-	depends on LCD_CLASS_DEVICE
-	default y
-
 config BACKLIGHT_CORGI
 	tristate "Sharp Corgi Backlight Driver (SL Series)"
-	depends on BACKLIGHT_DEVICE && PXA_SHARPSL
+	depends on BACKLIGHT_CLASS_DEVICE && PXA_SHARPSL
 	default y
 	help
 	  If you have a Sharp Zaurus SL-C7xx, SL-Cxx00 or SL-6000x say y to enable the
@@ -52,7 +42,7 @@ config BACKLIGHT_CORGI
 
 config BACKLIGHT_LOCOMO
 	tristate "Sharp LOCOMO LCD/Backlight Driver"
-	depends on BACKLIGHT_DEVICE && SHARP_LOCOMO
+	depends on BACKLIGHT_CLASS_DEVICE && SHARP_LOCOMO
 	default y
 	help
 	  If you have a Sharp Zaurus SL-5500 (Collie) or SL-5600 (Poodle) say y to
@@ -60,9 +50,16 @@ config BACKLIGHT_LOCOMO
 
 config BACKLIGHT_HP680
 	tristate "HP Jornada 680 Backlight Driver"
-	depends on BACKLIGHT_DEVICE && SH_HP6XX
+	depends on BACKLIGHT_CLASS_DEVICE && SH_HP6XX
 	default y
 	help
 	  If you have a HP Jornada 680, say y to enable the
 	  backlight driver.
 
+config BACKLIGHT_PROGEAR
+	tristate "Frontpath ProGear Backlight Driver"
+	depends on BACKLIGHT_CLASS_DEVICE && PCI && X86
+	default n
+	help
+	  If you have a Frontpath ProGear say Y to enable the
+	  backlight driver.
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 65e5553fc849..0c3ce46f5094 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
 obj-$(CONFIG_BACKLIGHT_CORGI)	+= corgi_bl.o
 obj-$(CONFIG_BACKLIGHT_HP680)	+= hp680_bl.o
 obj-$(CONFIG_BACKLIGHT_LOCOMO)	+= locomolcd.o
+obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 9601bfe309ac..c65e81ff3578 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -14,6 +14,9 @@
 #include <linux/err.h>
 #include <linux/fb.h>
 
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
 
 #if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \
 			   defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE))
@@ -28,19 +31,18 @@ static int fb_notifier_callback(struct notifier_block *self,
 	struct fb_event *evdata = data;
 
 	/* If we aren't interested in this event, skip it immediately ... */
-	if (event != FB_EVENT_BLANK)
+	if (event != FB_EVENT_BLANK && event != FB_EVENT_CONBLANK)
 		return 0;
 
 	bd = container_of(self, struct backlight_device, fb_notif);
-	down(&bd->sem);
-	if (bd->props)
-		if (!bd->props->check_fb ||
-		    bd->props->check_fb(evdata->info)) {
-			bd->props->fb_blank = *(int *)evdata->data;
-			if (likely(bd->props && bd->props->update_status))
-				bd->props->update_status(bd);
+	mutex_lock(&bd->ops_lock);
+	if (bd->ops)
+		if (!bd->ops->check_fb ||
+		    bd->ops->check_fb(evdata->info)) {
+			bd->props.fb_blank = *(int *)evdata->data;
+			backlight_update_status(bd);
 		}
-	up(&bd->sem);
+	mutex_unlock(&bd->ops_lock);
 	return 0;
 }
 
@@ -69,15 +71,9 @@ static inline void backlight_unregister_fb(struct backlight_device *bd)
 
 static ssize_t backlight_show_power(struct class_device *cdev, char *buf)
 {
-	int rc = -ENXIO;
 	struct backlight_device *bd = to_backlight_device(cdev);
 
-	down(&bd->sem);
-	if (likely(bd->props))
-		rc = sprintf(buf, "%d\n", bd->props->power);
-	up(&bd->sem);
-
-	return rc;
+	return sprintf(buf, "%d\n", bd->props.power);
 }
 
 static ssize_t backlight_store_power(struct class_device *cdev, const char *buf, size_t count)
@@ -93,30 +89,23 @@ static ssize_t backlight_store_power(struct class_device *cdev, const char *buf,
 	if (size != count)
 		return -EINVAL;
 
-	down(&bd->sem);
-	if (likely(bd->props)) {
+	mutex_lock(&bd->ops_lock);
+	if (bd->ops) {
 		pr_debug("backlight: set power to %d\n", power);
-		bd->props->power = power;
-		if (likely(bd->props->update_status))
-			bd->props->update_status(bd);
+		bd->props.power = power;
+		backlight_update_status(bd);
 		rc = count;
 	}
-	up(&bd->sem);
+	mutex_unlock(&bd->ops_lock);
 
 	return rc;
 }
 
 static ssize_t backlight_show_brightness(struct class_device *cdev, char *buf)
 {
-	int rc = -ENXIO;
 	struct backlight_device *bd = to_backlight_device(cdev);
 
-	down(&bd->sem);
-	if (likely(bd->props))
-		rc = sprintf(buf, "%d\n", bd->props->brightness);
-	up(&bd->sem);
-
-	return rc;
+	return sprintf(buf, "%d\n", bd->props.brightness);
 }
 
 static ssize_t backlight_store_brightness(struct class_device *cdev, const char *buf, size_t count)
@@ -132,35 +121,28 @@ static ssize_t backlight_store_brightness(struct class_device *cdev, const char
 	if (size != count)
 		return -EINVAL;
 
-	down(&bd->sem);
-	if (likely(bd->props)) {
-		if (brightness > bd->props->max_brightness)
+	mutex_lock(&bd->ops_lock);
+	if (bd->ops) {
+		if (brightness > bd->props.max_brightness)
 			rc = -EINVAL;
 		else {
 			pr_debug("backlight: set brightness to %d\n",
 				 brightness);
-			bd->props->brightness = brightness;
-			if (likely(bd->props->update_status))
-				bd->props->update_status(bd);
+			bd->props.brightness = brightness;
+			backlight_update_status(bd);
 			rc = count;
 		}
 	}
-	up(&bd->sem);
+	mutex_unlock(&bd->ops_lock);
 
 	return rc;
 }
 
 static ssize_t backlight_show_max_brightness(struct class_device *cdev, char *buf)
 {
-	int rc = -ENXIO;
 	struct backlight_device *bd = to_backlight_device(cdev);
 
-	down(&bd->sem);
-	if (likely(bd->props))
-		rc = sprintf(buf, "%d\n", bd->props->max_brightness);
-	up(&bd->sem);
-
-	return rc;
+	return sprintf(buf, "%d\n", bd->props.max_brightness);
 }
 
 static ssize_t backlight_show_actual_brightness(struct class_device *cdev,
@@ -169,10 +151,10 @@ static ssize_t backlight_show_actual_brightness(struct class_device *cdev,
 	int rc = -ENXIO;
 	struct backlight_device *bd = to_backlight_device(cdev);
 
-	down(&bd->sem);
-	if (likely(bd->props && bd->props->get_brightness))
-		rc = sprintf(buf, "%d\n", bd->props->get_brightness(bd));
-	up(&bd->sem);
+	mutex_lock(&bd->ops_lock);
+	if (bd->ops && bd->ops->get_brightness)
+		rc = sprintf(buf, "%d\n", bd->ops->get_brightness(bd));
+	mutex_unlock(&bd->ops_lock);
 
 	return rc;
 }
@@ -211,7 +193,7 @@ static const struct class_device_attribute bl_class_device_attributes[] = {
  *   respective framebuffer device).
  * @devdata: an optional pointer to be stored in the class_device. The
  *   methods may retrieve it by using class_get_devdata(&bd->class_dev).
- * @bp: the backlight properties structure.
+ * @ops: the backlight operations structure.
  *
  * Creates and registers new backlight class_device. Returns either an
  * ERR_PTR() or a pointer to the newly allocated device.
@@ -219,39 +201,42 @@ static const struct class_device_attribute bl_class_device_attributes[] = {
 struct backlight_device *backlight_device_register(const char *name,
 	struct device *dev,
 	void *devdata,
-	struct backlight_properties *bp)
+	struct backlight_ops *ops)
 {
 	int i, rc;
 	struct backlight_device *new_bd;
 
 	pr_debug("backlight_device_alloc: name=%s\n", name);
 
-	new_bd = kmalloc(sizeof(struct backlight_device), GFP_KERNEL);
-	if (unlikely(!new_bd))
+	new_bd = kzalloc(sizeof(struct backlight_device), GFP_KERNEL);
+	if (!new_bd)
 		return ERR_PTR(-ENOMEM);
 
-	init_MUTEX(&new_bd->sem);
-	new_bd->props = bp;
-	memset(&new_bd->class_dev, 0, sizeof(new_bd->class_dev));
+	mutex_init(&new_bd->update_lock);
+	mutex_init(&new_bd->ops_lock);
+	new_bd->ops = ops;
 	new_bd->class_dev.class = &backlight_class;
 	new_bd->class_dev.dev = dev;
 	strlcpy(new_bd->class_dev.class_id, name, KOBJ_NAME_LEN);
 	class_set_devdata(&new_bd->class_dev, devdata);
 
 	rc = class_device_register(&new_bd->class_dev);
-	if (unlikely(rc)) {
-error:		kfree(new_bd);
+	if (rc) {
+		kfree(new_bd);
 		return ERR_PTR(rc);
 	}
 
 	rc = backlight_register_fb(new_bd);
-	if (unlikely(rc))
-		goto error;
+	if (rc) {
+		class_device_unregister(&new_bd->class_dev);
+		return ERR_PTR(rc);
+	}
+
 
 	for (i = 0; i < ARRAY_SIZE(bl_class_device_attributes); i++) {
 		rc = class_device_create_file(&new_bd->class_dev,
 					      &bl_class_device_attributes[i]);
-		if (unlikely(rc)) {
+		if (rc) {
 			while (--i >= 0)
 				class_device_remove_file(&new_bd->class_dev,
 							 &bl_class_device_attributes[i]);
@@ -261,6 +246,13 @@ error:		kfree(new_bd);
 		}
 	}
 
+#ifdef CONFIG_PMAC_BACKLIGHT
+	mutex_lock(&pmac_backlight_mutex);
+	if (!pmac_backlight)
+		pmac_backlight = new_bd;
+	mutex_unlock(&pmac_backlight_mutex);
+#endif
+
 	return new_bd;
 }
 EXPORT_SYMBOL(backlight_device_register);
@@ -280,13 +272,20 @@ void backlight_device_unregister(struct backlight_device *bd)
 
 	pr_debug("backlight_device_unregister: name=%s\n", bd->class_dev.class_id);
 
+#ifdef CONFIG_PMAC_BACKLIGHT
+	mutex_lock(&pmac_backlight_mutex);
+	if (pmac_backlight == bd)
+		pmac_backlight = NULL;
+	mutex_unlock(&pmac_backlight_mutex);
+#endif
+
 	for (i = 0; i < ARRAY_SIZE(bl_class_device_attributes); i++)
 		class_device_remove_file(&bd->class_dev,
 					 &bl_class_device_attributes[i]);
 
-	down(&bd->sem);
-	bd->props = NULL;
-	up(&bd->sem);
+	mutex_lock(&bd->ops_lock);
+	bd->ops = NULL;
+	mutex_unlock(&bd->ops_lock);
 
 	backlight_unregister_fb(bd);
 
diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c
index fde1d9518123..ce00e18a4e5d 100644
--- a/drivers/video/backlight/corgi_bl.c
+++ b/drivers/video/backlight/corgi_bl.c
@@ -22,7 +22,6 @@
 #include <asm/hardware/sharpsl_pm.h>
 
 static int corgibl_intensity;
-static DEFINE_MUTEX(bl_mutex);
 static struct backlight_properties corgibl_data;
 static struct backlight_device *corgi_backlight_device;
 static struct corgibl_machinfo *bl_machinfo;
@@ -34,20 +33,18 @@ static unsigned long corgibl_flags;
 static int corgibl_send_intensity(struct backlight_device *bd)
 {
 	void (*corgi_kick_batt)(void);
-	int intensity = bd->props->brightness;
+	int intensity = bd->props.brightness;
 
-	if (bd->props->power != FB_BLANK_UNBLANK)
+	if (bd->props.power != FB_BLANK_UNBLANK)
 		intensity = 0;
-	if (bd->props->fb_blank != FB_BLANK_UNBLANK)
+	if (bd->props.fb_blank != FB_BLANK_UNBLANK)
 		intensity = 0;
 	if (corgibl_flags & CORGIBL_SUSPENDED)
 		intensity = 0;
 	if (corgibl_flags & CORGIBL_BATTLOW)
 		intensity &= bl_machinfo->limit_mask;
 
- 	mutex_lock(&bl_mutex);
 	bl_machinfo->set_bl_intensity(intensity);
-	mutex_unlock(&bl_mutex);
 
 	corgibl_intensity = intensity;
 
@@ -61,17 +58,21 @@ static int corgibl_send_intensity(struct backlight_device *bd)
 }
 
 #ifdef CONFIG_PM
-static int corgibl_suspend(struct platform_device *dev, pm_message_t state)
+static int corgibl_suspend(struct platform_device *pdev, pm_message_t state)
 {
+	struct backlight_device *bd = platform_get_drvdata(pdev);
+
 	corgibl_flags |= CORGIBL_SUSPENDED;
-	corgibl_send_intensity(corgi_backlight_device);
+	backlight_update_status(bd);
 	return 0;
 }
 
-static int corgibl_resume(struct platform_device *dev)
+static int corgibl_resume(struct platform_device *pdev)
 {
+	struct backlight_device *bd = platform_get_drvdata(pdev);
+
 	corgibl_flags &= ~CORGIBL_SUSPENDED;
-	corgibl_send_intensity(corgi_backlight_device);
+	backlight_update_status(bd);
 	return 0;
 }
 #else
@@ -84,12 +85,6 @@ static int corgibl_get_intensity(struct backlight_device *bd)
 	return corgibl_intensity;
 }
 
-static int corgibl_set_intensity(struct backlight_device *bd)
-{
-	corgibl_send_intensity(corgi_backlight_device);
-	return 0;
-}
-
 /*
  * Called when the battery is low to limit the backlight intensity.
  * If limit==0 clear any limit, otherwise limit the intensity
@@ -100,15 +95,14 @@ void corgibl_limit_intensity(int limit)
 		corgibl_flags |= CORGIBL_BATTLOW;
 	else
 		corgibl_flags &= ~CORGIBL_BATTLOW;
-	corgibl_send_intensity(corgi_backlight_device);
+	backlight_update_status(corgi_backlight_device);
 }
 EXPORT_SYMBOL(corgibl_limit_intensity);
 
 
-static struct backlight_properties corgibl_data = {
-	.owner          = THIS_MODULE,
+static struct backlight_ops corgibl_ops = {
 	.get_brightness = corgibl_get_intensity,
-	.update_status  = corgibl_set_intensity,
+	.update_status  = corgibl_send_intensity,
 };
 
 static int corgibl_probe(struct platform_device *pdev)
@@ -116,30 +110,34 @@ static int corgibl_probe(struct platform_device *pdev)
 	struct corgibl_machinfo *machinfo = pdev->dev.platform_data;
 
 	bl_machinfo = machinfo;
-	corgibl_data.max_brightness = machinfo->max_intensity;
 	if (!machinfo->limit_mask)
 		machinfo->limit_mask = -1;
 
 	corgi_backlight_device = backlight_device_register ("corgi-bl",
-		&pdev->dev, NULL, &corgibl_data);
+		&pdev->dev, NULL, &corgibl_ops);
 	if (IS_ERR (corgi_backlight_device))
 		return PTR_ERR (corgi_backlight_device);
 
-	corgibl_data.power = FB_BLANK_UNBLANK;
-	corgibl_data.brightness = machinfo->default_intensity;
-	corgibl_send_intensity(corgi_backlight_device);
+	platform_set_drvdata(pdev, corgi_backlight_device);
+
+	corgi_backlight_device->props.max_brightness = machinfo->max_intensity;
+	corgi_backlight_device->props.power = FB_BLANK_UNBLANK;
+	corgi_backlight_device->props.brightness = machinfo->default_intensity;
+	backlight_update_status(corgi_backlight_device);
 
 	printk("Corgi Backlight Driver Initialized.\n");
 	return 0;
 }
 
-static int corgibl_remove(struct platform_device *dev)
+static int corgibl_remove(struct platform_device *pdev)
 {
+	struct backlight_device *bd = platform_get_drvdata(pdev);
+
 	corgibl_data.power = 0;
 	corgibl_data.brightness = 0;
-	corgibl_send_intensity(corgi_backlight_device);
+	backlight_update_status(bd);
 
-	backlight_device_unregister(corgi_backlight_device);
+	backlight_device_unregister(bd);
 
 	printk("Corgi Backlight Driver Unloaded\n");
 	return 0;
diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c
index c07d8207fb54..0899fccbd570 100644
--- a/drivers/video/backlight/hp680_bl.c
+++ b/drivers/video/backlight/hp680_bl.c
@@ -28,17 +28,16 @@
 static int hp680bl_suspended;
 static int current_intensity = 0;
 static DEFINE_SPINLOCK(bl_lock);
-static struct backlight_device *hp680_backlight_device;
 
 static void hp680bl_send_intensity(struct backlight_device *bd)
 {
 	unsigned long flags;
 	u16 v;
-	int intensity = bd->props->brightness;
+	int intensity = bd->props.brightness;
 
-	if (bd->props->power != FB_BLANK_UNBLANK)
+	if (bd->props.power != FB_BLANK_UNBLANK)
 		intensity = 0;
-	if (bd->props->fb_blank != FB_BLANK_UNBLANK)
+	if (bd->props.fb_blank != FB_BLANK_UNBLANK)
 		intensity = 0;
 	if (hp680bl_suspended)
 		intensity = 0;
@@ -66,17 +65,21 @@ static void hp680bl_send_intensity(struct backlight_device *bd)
 
 
 #ifdef CONFIG_PM
-static int hp680bl_suspend(struct platform_device *dev, pm_message_t state)
+static int hp680bl_suspend(struct platform_device *pdev, pm_message_t state)
 {
+	struct backlight_device *bd = platform_get_drvdata(pdev);
+
 	hp680bl_suspended = 1;
-	hp680bl_send_intensity(hp680_backlight_device);
+	hp680bl_send_intensity(bd);
 	return 0;
 }
 
-static int hp680bl_resume(struct platform_device *dev)
+static int hp680bl_resume(struct platform_device *pdev)
 {
+	struct backlight_device *bd = platform_get_drvdata(pdev);
+
 	hp680bl_suspended = 0;
-	hp680bl_send_intensity(hp680_backlight_device);
+	hp680bl_send_intensity(bd);
 	return 0;
 }
 #else
@@ -95,33 +98,38 @@ static int hp680bl_get_intensity(struct backlight_device *bd)
 	return current_intensity;
 }
 
-static struct backlight_properties hp680bl_data = {
-	.owner		= THIS_MODULE,
-	.max_brightness = HP680_MAX_INTENSITY,
+static struct backlight_ops hp680bl_ops = {
 	.get_brightness = hp680bl_get_intensity,
 	.update_status  = hp680bl_set_intensity,
 };
 
-static int __init hp680bl_probe(struct platform_device *dev)
+static int __init hp680bl_probe(struct platform_device *pdev)
 {
-	hp680_backlight_device = backlight_device_register ("hp680-bl",
-		&dev->dev, NULL, &hp680bl_data);
-	if (IS_ERR (hp680_backlight_device))
-		return PTR_ERR (hp680_backlight_device);
+	struct backlight_device *bd;
 
-	hp680_backlight_device->props->brightness = HP680_DEFAULT_INTENSITY;
-	hp680bl_send_intensity(hp680_backlight_device);
+	bd = backlight_device_register ("hp680-bl", &pdev->dev, NULL,
+		    &hp680bl_ops);
+	if (IS_ERR(bd))
+		return PTR_ERR(bd);
+
+	platform_set_drvdata(pdev, bd);
+
+	bd->props.max_brightness = HP680_MAX_INTENSITY;
+	bd->props.brightness = HP680_DEFAULT_INTENSITY;
+	hp680bl_send_intensity(bd);
 
 	return 0;
 }
 
-static int hp680bl_remove(struct platform_device *dev)
+static int hp680bl_remove(struct platform_device *pdev)
 {
+	struct backlight_device *bd = platform_get_drvdata(pdev);
+
 	hp680bl_data.brightness = 0;
 	hp680bl_data.power = 0;
-	hp680bl_send_intensity(hp680_backlight_device);
+	hp680bl_send_intensity(bd);
 
-	backlight_device_unregister(hp680_backlight_device);
+	backlight_device_unregister(bd);
 
 	return 0;
 }
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index f6e041627edb..6ef8f0a7a137 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -31,11 +31,11 @@ static int fb_notifier_callback(struct notifier_block *self,
 		return 0;
 
 	ld = container_of(self, struct lcd_device, fb_notif);
-	down(&ld->sem);
-	if (ld->props)
-		if (!ld->props->check_fb || ld->props->check_fb(evdata->info))
-			ld->props->set_power(ld, *(int *)evdata->data);
-	up(&ld->sem);
+	mutex_lock(&ld->ops_lock);
+	if (ld->ops)
+		if (!ld->ops->check_fb || ld->ops->check_fb(evdata->info))
+			ld->ops->set_power(ld, *(int *)evdata->data);
+	mutex_unlock(&ld->ops_lock);
 	return 0;
 }
 
@@ -66,12 +66,12 @@ static ssize_t lcd_show_power(struct class_device *cdev, char *buf)
 	int rc;
 	struct lcd_device *ld = to_lcd_device(cdev);
 
-	down(&ld->sem);
-	if (likely(ld->props && ld->props->get_power))
-		rc = sprintf(buf, "%d\n", ld->props->get_power(ld));
+	mutex_lock(&ld->ops_lock);
+	if (ld->ops && ld->ops->get_power)
+		rc = sprintf(buf, "%d\n", ld->ops->get_power(ld));
 	else
 		rc = -ENXIO;
-	up(&ld->sem);
+	mutex_unlock(&ld->ops_lock);
 
 	return rc;
 }
@@ -89,13 +89,13 @@ static ssize_t lcd_store_power(struct class_device *cdev, const char *buf, size_
 	if (size != count)
 		return -EINVAL;
 
-	down(&ld->sem);
-	if (likely(ld->props && ld->props->set_power)) {
+	mutex_lock(&ld->ops_lock);
+	if (ld->ops && ld->ops->set_power) {
 		pr_debug("lcd: set power to %d\n", power);
-		ld->props->set_power(ld, power);
+		ld->ops->set_power(ld, power);
 		rc = count;
 	}
-	up(&ld->sem);
+	mutex_unlock(&ld->ops_lock);
 
 	return rc;
 }
@@ -105,10 +105,10 @@ static ssize_t lcd_show_contrast(struct class_device *cdev, char *buf)
 	int rc = -ENXIO;
 	struct lcd_device *ld = to_lcd_device(cdev);
 
-	down(&ld->sem);
-	if (likely(ld->props && ld->props->get_contrast))
-		rc = sprintf(buf, "%d\n", ld->props->get_contrast(ld));
-	up(&ld->sem);
+	mutex_lock(&ld->ops_lock);
+	if (ld->ops && ld->ops->get_contrast)
+		rc = sprintf(buf, "%d\n", ld->ops->get_contrast(ld));
+	mutex_unlock(&ld->ops_lock);
 
 	return rc;
 }
@@ -126,28 +126,22 @@ static ssize_t lcd_store_contrast(struct class_device *cdev, const char *buf, si
 	if (size != count)
 		return -EINVAL;
 
-	down(&ld->sem);
-	if (likely(ld->props && ld->props->set_contrast)) {
+	mutex_lock(&ld->ops_lock);
+	if (ld->ops && ld->ops->set_contrast) {
 		pr_debug("lcd: set contrast to %d\n", contrast);
-		ld->props->set_contrast(ld, contrast);
+		ld->ops->set_contrast(ld, contrast);
 		rc = count;
 	}
-	up(&ld->sem);
+	mutex_unlock(&ld->ops_lock);
 
 	return rc;
 }
 
 static ssize_t lcd_show_max_contrast(struct class_device *cdev, char *buf)
 {
-	int rc = -ENXIO;
 	struct lcd_device *ld = to_lcd_device(cdev);
 
-	down(&ld->sem);
-	if (likely(ld->props))
-		rc = sprintf(buf, "%d\n", ld->props->max_contrast);
-	up(&ld->sem);
-
-	return rc;
+	return sprintf(buf, "%d\n", ld->props.max_contrast);
 }
 
 static void lcd_class_release(struct class_device *dev)
@@ -180,45 +174,46 @@ static const struct class_device_attribute lcd_class_device_attributes[] = {
  *   respective framebuffer device).
  * @devdata: an optional pointer to be stored in the class_device. The
  *   methods may retrieve it by using class_get_devdata(ld->class_dev).
- * @lp: the lcd properties structure.
+ * @ops: the lcd operations structure.
  *
  * Creates and registers a new lcd class_device. Returns either an ERR_PTR()
  * or a pointer to the newly allocated device.
  */
 struct lcd_device *lcd_device_register(const char *name, void *devdata,
-				       struct lcd_properties *lp)
+				       struct lcd_ops *ops)
 {
 	int i, rc;
 	struct lcd_device *new_ld;
 
 	pr_debug("lcd_device_register: name=%s\n", name);
 
-	new_ld = kmalloc(sizeof(struct lcd_device), GFP_KERNEL);
-	if (unlikely(!new_ld))
+	new_ld = kzalloc(sizeof(struct lcd_device), GFP_KERNEL);
+	if (!new_ld)
 		return ERR_PTR(-ENOMEM);
 
-	init_MUTEX(&new_ld->sem);
-	new_ld->props = lp;
-	memset(&new_ld->class_dev, 0, sizeof(new_ld->class_dev));
+	mutex_init(&new_ld->ops_lock);
+	mutex_init(&new_ld->update_lock);
+	new_ld->ops = ops;
 	new_ld->class_dev.class = &lcd_class;
 	strlcpy(new_ld->class_dev.class_id, name, KOBJ_NAME_LEN);
 	class_set_devdata(&new_ld->class_dev, devdata);
 
 	rc = class_device_register(&new_ld->class_dev);
-	if (unlikely(rc)) {
-error:		kfree(new_ld);
+	if (rc) {
+		kfree(new_ld);
 		return ERR_PTR(rc);
 	}
 
 	rc = lcd_register_fb(new_ld);
-
-	if (unlikely(rc))
-		goto error;
+	if (rc) {
+		class_device_unregister(&new_ld->class_dev);
+		return ERR_PTR(rc);
+	}
 
 	for (i = 0; i < ARRAY_SIZE(lcd_class_device_attributes); i++) {
 		rc = class_device_create_file(&new_ld->class_dev,
 					      &lcd_class_device_attributes[i]);
-		if (unlikely(rc)) {
+		if (rc) {
 			while (--i >= 0)
 				class_device_remove_file(&new_ld->class_dev,
 							 &lcd_class_device_attributes[i]);
@@ -251,9 +246,9 @@ void lcd_device_unregister(struct lcd_device *ld)
 		class_device_remove_file(&ld->class_dev,
 					 &lcd_class_device_attributes[i]);
 
-	down(&ld->sem);
-	ld->props = NULL;
-	up(&ld->sem);
+	mutex_lock(&ld->ops_lock);
+	ld->ops = NULL;
+	mutex_unlock(&ld->ops_lock);
 	lcd_unregister_fb(ld);
 	class_device_unregister(&ld->class_dev);
 }
diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c
index fc812d96c31d..d1312477813e 100644
--- a/drivers/video/backlight/locomolcd.c
+++ b/drivers/video/backlight/locomolcd.c
@@ -112,11 +112,11 @@ static int current_intensity;
 
 static int locomolcd_set_intensity(struct backlight_device *bd)
 {
-	int intensity = bd->props->brightness;
+	int intensity = bd->props.brightness;
 
-	if (bd->props->power != FB_BLANK_UNBLANK)
+	if (bd->props.power != FB_BLANK_UNBLANK)
 		intensity = 0;
-	if (bd->props->fb_blank != FB_BLANK_UNBLANK)
+	if (bd->props.fb_blank != FB_BLANK_UNBLANK)
 		intensity = 0;
 	if (locomolcd_flags & LOCOMOLCD_SUSPENDED)
 		intensity = 0;
@@ -141,11 +141,9 @@ static int locomolcd_get_intensity(struct backlight_device *bd)
 	return current_intensity;
 }
 
-static struct backlight_properties locomobl_data = {
-	.owner		= THIS_MODULE,
+static struct backlight_ops locomobl_data = {
 	.get_brightness = locomolcd_get_intensity,
 	.update_status  = locomolcd_set_intensity,
-	.max_brightness = 4,
 };
 
 #ifdef CONFIG_PM
@@ -190,7 +188,8 @@ static int locomolcd_probe(struct locomo_dev *ldev)
 		return PTR_ERR (locomolcd_bl_device);
 
 	/* Set up frontlight so that screen is readable */
-	locomobl_data.brightness = 2;
+	locomolcd_bl_device->props.max_brightness = 4,
+	locomolcd_bl_device->props.brightness = 2;
 	locomolcd_set_intensity(locomolcd_bl_device);
 
 	return 0;
diff --git a/drivers/video/backlight/progear_bl.c b/drivers/video/backlight/progear_bl.c
new file mode 100644
index 000000000000..702269357861
--- /dev/null
+++ b/drivers/video/backlight/progear_bl.c
@@ -0,0 +1,153 @@
+/*
+ *  Backlight Driver for Frontpath ProGear HX1050+
+ *
+ *  Copyright (c) 2006 Marcin Juszkiewicz
+ *
+ *  Based on Progear LCD driver by M Schacht
+ *  <mschacht at alumni dot washington dot edu>
+ *
+ *  Based on Sharp's Corgi Backlight Driver
+ *  Based on Backlight Driver for HP Jornada 680
+ *
+ *  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/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+#include <linux/pci.h>
+#include <asm/uaccess.h>
+
+#define PMU_LPCR               0xB0
+#define SB_MPS1                0x61
+#define HW_LEVEL_MAX           0x77
+#define HW_LEVEL_MIN           0x4f
+
+static struct pci_dev *pmu_dev = NULL;
+static struct pci_dev *sb_dev = NULL;
+
+static int progearbl_set_intensity(struct backlight_device *bd)
+{
+	int intensity = bd->props.brightness;
+
+	if (bd->props.power != FB_BLANK_UNBLANK)
+		intensity = 0;
+	if (bd->props.fb_blank != FB_BLANK_UNBLANK)
+		intensity = 0;
+
+	pci_write_config_byte(pmu_dev, PMU_LPCR, intensity + HW_LEVEL_MIN);
+
+	return 0;
+}
+
+static int progearbl_get_intensity(struct backlight_device *bd)
+{
+	u8 intensity;
+	pci_read_config_byte(pmu_dev, PMU_LPCR, &intensity);
+
+	return intensity - HW_LEVEL_MIN;
+}
+
+static struct backlight_ops progearbl_ops = {
+	.get_brightness = progearbl_get_intensity,
+	.update_status = progearbl_set_intensity,
+};
+
+static int progearbl_probe(struct platform_device *pdev)
+{
+	u8 temp;
+	struct backlight_device *progear_backlight_device;
+
+	pmu_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, 0);
+	if (!pmu_dev) {
+		printk("ALI M7101 PMU not found.\n");
+		return -ENODEV;
+	}
+
+	sb_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, 0);
+	if (!sb_dev) {
+		printk("ALI 1533 SB not found.\n");
+		pci_dev_put(pmu_dev);
+		return -ENODEV;
+	}
+
+	/*     Set SB_MPS1 to enable brightness control. */
+	pci_read_config_byte(sb_dev, SB_MPS1, &temp);
+	pci_write_config_byte(sb_dev, SB_MPS1, temp | 0x20);
+
+	progear_backlight_device = backlight_device_register("progear-bl",
+							     &pdev->dev, NULL,
+							     &progearbl_ops);
+	if (IS_ERR(progear_backlight_device))
+		return PTR_ERR(progear_backlight_device);
+
+	platform_set_drvdata(pdev, progear_backlight_device);
+
+	progear_backlight_device->props.power = FB_BLANK_UNBLANK;
+	progear_backlight_device->props.brightness = HW_LEVEL_MAX - HW_LEVEL_MIN;
+	progear_backlight_device->props.max_brightness = HW_LEVEL_MAX - HW_LEVEL_MIN;
+	progearbl_set_intensity(progear_backlight_device);
+
+	return 0;
+}
+
+static int progearbl_remove(struct platform_device *pdev)
+{
+	struct backlight_device *bd = platform_get_drvdata(pdev);
+	backlight_device_unregister(bd);
+
+	return 0;
+}
+
+static struct platform_driver progearbl_driver = {
+	.probe = progearbl_probe,
+	.remove = progearbl_remove,
+	.driver = {
+		   .name = "progear-bl",
+		   },
+};
+
+static struct platform_device *progearbl_device;
+
+static int __init progearbl_init(void)
+{
+	int ret = platform_driver_register(&progearbl_driver);
+
+	if (!ret) {
+		progearbl_device = platform_device_alloc("progear-bl", -1);
+		if (!progearbl_device)
+			return -ENOMEM;
+
+		ret = platform_device_add(progearbl_device);
+
+		if (ret) {
+			platform_device_put(progearbl_device);
+			platform_driver_unregister(&progearbl_driver);
+		}
+	}
+
+	return ret;
+}
+
+static void __exit progearbl_exit(void)
+{
+	pci_dev_put(pmu_dev);
+	pci_dev_put(sb_dev);
+
+	platform_device_unregister(progearbl_device);
+	platform_driver_unregister(&progearbl_driver);
+}
+
+module_init(progearbl_init);
+module_exit(progearbl_exit);
+
+MODULE_AUTHOR("Marcin Juszkiewicz <linux@hrw.one.pl>");
+MODULE_DESCRIPTION("ProGear Backlight Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index 73cb426bf2d7..af313bf1a2da 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -145,26 +145,6 @@ static int chipsfb_set_par(struct fb_info *info)
 
 static int chipsfb_blank(int blank, struct fb_info *info)
 {
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_lock(&pmac_backlight_mutex);
-
-	if (pmac_backlight) {
-		/* used to disable backlight only for blank > 1, but it seems
-		 * useful at blank = 1 too (saves battery, extends backlight
-		 * life)
-	 	 */
-		down(&pmac_backlight->sem);
-		if (blank)
-			pmac_backlight->props->power = FB_BLANK_POWERDOWN;
-		else
-			pmac_backlight->props->power = FB_BLANK_UNBLANK;
-		pmac_backlight->props->update_status(pmac_backlight);
-		up(&pmac_backlight->sem);
-	}
-
-	mutex_unlock(&pmac_backlight_mutex);
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
 	return 1;	/* get fb_blank to set the colormap to all black */
 }
 
@@ -415,10 +395,8 @@ chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
 	/* turn on the backlight */
 	mutex_lock(&pmac_backlight_mutex);
 	if (pmac_backlight) {
-		down(&pmac_backlight->sem);
-		pmac_backlight->props->power = FB_BLANK_UNBLANK;
-		pmac_backlight->props->update_status(pmac_backlight);
-		up(&pmac_backlight->sem);
+		pmac_backlight->props.power = FB_BLANK_UNBLANK;
+		backlight_update_status(pmac_backlight);
 	}
 	mutex_unlock(&pmac_backlight_mutex);
 #endif /* CONFIG_PMAC_BACKLIGHT */
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index be3f2c3f132c..0429fd2cece0 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -2233,6 +2233,8 @@ static int fbcon_switch(struct vc_data *vc)
 static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info,
 				int blank)
 {
+	struct fb_event event;
+
 	if (blank) {
 		unsigned short charmask = vc->vc_hi_font_mask ?
 			0x1ff : 0xff;
@@ -2243,6 +2245,11 @@ static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info,
 		fbcon_clear(vc, 0, 0, vc->vc_rows, vc->vc_cols);
 		vc->vc_video_erase_char = oldc;
 	}
+
+
+	event.info = info;
+	event.data = &blank;
+	fb_notifier_call_chain(FB_EVENT_CONBLANK, &event);
 }
 
 static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index 818fb09105f9..40c80c8190e2 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -59,7 +59,7 @@ struct fb_info *framebuffer_alloc(size_t size, struct device *dev)
 	info->device = dev;
 
 #ifdef CONFIG_FB_BACKLIGHT
-	mutex_init(&info->bl_mutex);
+	mutex_init(&info->bl_curve_mutex);
 #endif
 
 	return info;
@@ -445,10 +445,10 @@ static ssize_t store_bl_curve(struct device *device,
 	/* If there has been an error in the input data, we won't
 	 * reach this loop.
 	 */
-	mutex_lock(&fb_info->bl_mutex);
+	mutex_lock(&fb_info->bl_curve_mutex);
 	for (i = 0; i < FB_BACKLIGHT_LEVELS; ++i)
 		fb_info->bl_curve[i] = tmp_curve[i];
-	mutex_unlock(&fb_info->bl_mutex);
+	mutex_unlock(&fb_info->bl_curve_mutex);
 
 	return count;
 }
@@ -466,7 +466,7 @@ static ssize_t show_bl_curve(struct device *device,
 	if (!fb_info || !fb_info->bl_dev)
 		return -ENODEV;
 
-	mutex_lock(&fb_info->bl_mutex);
+	mutex_lock(&fb_info->bl_curve_mutex);
 	for (i = 0; i < FB_BACKLIGHT_LEVELS; i += 8)
 		len += snprintf(&buf[len], PAGE_SIZE,
 				"%02x %02x %02x %02x %02x %02x %02x %02x\n",
@@ -478,7 +478,7 @@ static ssize_t show_bl_curve(struct device *device,
 				fb_info->bl_curve[i + 5],
 				fb_info->bl_curve[i + 6],
 				fb_info->bl_curve[i + 7]);
-	mutex_unlock(&fb_info->bl_mutex);
+	mutex_unlock(&fb_info->bl_curve_mutex);
 
 	return len;
 }
@@ -552,6 +552,8 @@ void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max)
 {
 	unsigned int i, flat, count, range = (max - min);
 
+	mutex_lock(&fb_info->bl_curve_mutex);
+
 	fb_info->bl_curve[0] = off;
 
 	for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat)
@@ -560,6 +562,8 @@ void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max)
 	count = FB_BACKLIGHT_LEVELS * 15 / 16;
 	for (i = 0; i < count; ++i)
 		fb_info->bl_curve[flat + i] = min + (range * (i + 1) / count);
+
+	mutex_unlock(&fb_info->bl_curve_mutex);
 }
 EXPORT_SYMBOL_GPL(fb_bl_default_curve);
 #endif
diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c
index df934bd21899..b7016e9b9e13 100644
--- a/drivers/video/nvidia/nv_backlight.c
+++ b/drivers/video/nvidia/nv_backlight.c
@@ -16,11 +16,6 @@
 #include "nv_type.h"
 #include "nv_proto.h"
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-#include <asm/backlight.h>
-#include <asm/machdep.h>
-#endif
-
 /* We do not have any information about which values are allowed, thus
  * we used safe values.
  */
@@ -30,7 +25,6 @@
 
 static struct backlight_properties nvidia_bl_data;
 
-/* Call with fb_info->bl_mutex held */
 static int nvidia_bl_get_level_brightness(struct nvidia_par *par,
 		int level)
 {
@@ -38,6 +32,7 @@ static int nvidia_bl_get_level_brightness(struct nvidia_par *par,
 	int nlevel;
 
 	/* Get and convert the value */
+	/* No locking of bl_curve since we read a single value */
 	nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP;
 
 	if (nlevel < 0)
@@ -50,8 +45,7 @@ static int nvidia_bl_get_level_brightness(struct nvidia_par *par,
 	return nlevel;
 }
 
-/* Call with fb_info->bl_mutex held */
-static int __nvidia_bl_update_status(struct backlight_device *bd)
+static int nvidia_bl_update_status(struct backlight_device *bd)
 {
 	struct nvidia_par *par = class_get_devdata(&bd->class_dev);
 	u32 tmp_pcrt, tmp_pmc, fpcontrol;
@@ -60,11 +54,11 @@ static int __nvidia_bl_update_status(struct backlight_device *bd)
 	if (!par->FlatPanel)
 		return 0;
 
-	if (bd->props->power != FB_BLANK_UNBLANK ||
-	    bd->props->fb_blank != FB_BLANK_UNBLANK)
+	if (bd->props.power != FB_BLANK_UNBLANK ||
+	    bd->props.fb_blank != FB_BLANK_UNBLANK)
 		level = 0;
 	else
-		level = bd->props->brightness;
+		level = bd->props.brightness;
 
 	tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF;
 	tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC;
@@ -85,45 +79,16 @@ static int __nvidia_bl_update_status(struct backlight_device *bd)
 	return 0;
 }
 
-static int nvidia_bl_update_status(struct backlight_device *bd)
-{
-	struct nvidia_par *par = class_get_devdata(&bd->class_dev);
-	struct fb_info *info = pci_get_drvdata(par->pci_dev);
-	int ret;
-
-	mutex_lock(&info->bl_mutex);
-	ret = __nvidia_bl_update_status(bd);
-	mutex_unlock(&info->bl_mutex);
-
-	return ret;
-}
-
 static int nvidia_bl_get_brightness(struct backlight_device *bd)
 {
-	return bd->props->brightness;
+	return bd->props.brightness;
 }
 
-static struct backlight_properties nvidia_bl_data = {
-	.owner		= THIS_MODULE,
+static struct backlight_ops nvidia_bl_ops = {
 	.get_brightness = nvidia_bl_get_brightness,
 	.update_status	= nvidia_bl_update_status,
-	.max_brightness = (FB_BACKLIGHT_LEVELS - 1),
 };
 
-void nvidia_bl_set_power(struct fb_info *info, int power)
-{
-	mutex_lock(&info->bl_mutex);
-
-	if (info->bl_dev) {
-		down(&info->bl_dev->sem);
-		info->bl_dev->props->power = power;
-		__nvidia_bl_update_status(info->bl_dev);
-		up(&info->bl_dev->sem);
-	}
-
-	mutex_unlock(&info->bl_mutex);
-}
-
 void nvidia_bl_init(struct nvidia_par *par)
 {
 	struct fb_info *info = pci_get_drvdata(par->pci_dev);
@@ -141,32 +106,22 @@ void nvidia_bl_init(struct nvidia_par *par)
 
 	snprintf(name, sizeof(name), "nvidiabl%d", info->node);
 
-	bd = backlight_device_register(name, info->dev, par, &nvidia_bl_data);
+	bd = backlight_device_register(name, info->dev, par, &nvidia_bl_ops);
 	if (IS_ERR(bd)) {
 		info->bl_dev = NULL;
 		printk(KERN_WARNING "nvidia: Backlight registration failed\n");
 		goto error;
 	}
 
-	mutex_lock(&info->bl_mutex);
 	info->bl_dev = bd;
 	fb_bl_default_curve(info, 0,
 		0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL,
 		0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL);
-	mutex_unlock(&info->bl_mutex);
 
-	down(&bd->sem);
-	bd->props->brightness = nvidia_bl_data.max_brightness;
-	bd->props->power = FB_BLANK_UNBLANK;
-	bd->props->update_status(bd);
-	up(&bd->sem);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_lock(&pmac_backlight_mutex);
-	if (!pmac_backlight)
-		pmac_backlight = bd;
-	mutex_unlock(&pmac_backlight_mutex);
-#endif
+	bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+	bd->props.brightness = nvidia_bl_data.max_brightness;
+	bd->props.power = FB_BLANK_UNBLANK;
+	backlight_update_status(bd);
 
 	printk("nvidia: Backlight initialized (%s)\n", name);
 
@@ -179,25 +134,8 @@ error:
 void nvidia_bl_exit(struct nvidia_par *par)
 {
 	struct fb_info *info = pci_get_drvdata(par->pci_dev);
+	struct backlight_device *bd = info->bl_dev;
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_lock(&pmac_backlight_mutex);
-#endif
-
-	mutex_lock(&info->bl_mutex);
-	if (info->bl_dev) {
-#ifdef CONFIG_PMAC_BACKLIGHT
-		if (pmac_backlight == info->bl_dev)
-			pmac_backlight = NULL;
-#endif
-
-		backlight_device_unregister(info->bl_dev);
-
-		printk("nvidia: Backlight unloaded\n");
-	}
-	mutex_unlock(&info->bl_mutex);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_unlock(&pmac_backlight_mutex);
-#endif
+	backlight_device_unregister(bd);
+	printk("nvidia: Backlight unloaded\n");
 }
diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h
index 43058d0cf5b7..ff5c410355ea 100644
--- a/drivers/video/nvidia/nv_proto.h
+++ b/drivers/video/nvidia/nv_proto.h
@@ -67,11 +67,9 @@ extern int nvidiafb_sync(struct fb_info *info);
 #ifdef CONFIG_FB_NVIDIA_BACKLIGHT
 extern void nvidia_bl_init(struct nvidia_par *par);
 extern void nvidia_bl_exit(struct nvidia_par *par);
-extern void nvidia_bl_set_power(struct fb_info *info, int power);
 #else
 static inline void nvidia_bl_init(struct nvidia_par *par) {}
 static inline void nvidia_bl_exit(struct nvidia_par *par) {}
-static inline void nvidia_bl_set_power(struct fb_info *info, int power) {}
 #endif
 
 #endif				/* __NV_PROTO_H__ */
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index 8e5b484db649..c18e9557ca30 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -938,8 +938,6 @@ static int nvidiafb_blank(int blank, struct fb_info *info)
 	NVWriteSeq(par, 0x01, tmp);
 	NVWriteCrtc(par, 0x1a, vesa);
 
-	nvidia_bl_set_power(info, blank);
-
 	NVTRACE_LEAVE();
 
 	return 0;
@@ -1352,9 +1350,10 @@ static void __devexit nvidiafb_remove(struct pci_dev *pd)
 
 	NVTRACE_ENTER();
 
+	unregister_framebuffer(info);
+
 	nvidia_bl_exit(par);
 
-	unregister_framebuffer(info);
 #ifdef CONFIG_MTRR
 	if (par->mtrr.vram_valid)
 		mtrr_del(par->mtrr.vram, info->fix.smem_start,
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index f2e9b742c92f..f8a3d608b208 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -282,7 +282,6 @@ static const struct riva_regs reg_template = {
 
 static struct backlight_properties riva_bl_data;
 
-/* Call with fb_info->bl_mutex held */
 static int riva_bl_get_level_brightness(struct riva_par *par,
 		int level)
 {
@@ -290,6 +289,7 @@ static int riva_bl_get_level_brightness(struct riva_par *par,
 	int nlevel;
 
 	/* Get and convert the value */
+	/* No locking on bl_curve since accessing a single value */
 	nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP;
 
 	if (nlevel < 0)
@@ -302,18 +302,17 @@ static int riva_bl_get_level_brightness(struct riva_par *par,
 	return nlevel;
 }
 
-/* Call with fb_info->bl_mutex held */
-static int __riva_bl_update_status(struct backlight_device *bd)
+static int riva_bl_update_status(struct backlight_device *bd)
 {
 	struct riva_par *par = class_get_devdata(&bd->class_dev);
 	U032 tmp_pcrt, tmp_pmc;
 	int level;
 
-	if (bd->props->power != FB_BLANK_UNBLANK ||
-	    bd->props->fb_blank != FB_BLANK_UNBLANK)
+	if (bd->props.power != FB_BLANK_UNBLANK ||
+	    bd->props.fb_blank != FB_BLANK_UNBLANK)
 		level = 0;
 	else
-		level = bd->props->brightness;
+		level = bd->props.brightness;
 
 	tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF;
 	tmp_pcrt = par->riva.PCRTC0[0x081C/4] & 0xFFFFFFFC;
@@ -328,45 +327,16 @@ static int __riva_bl_update_status(struct backlight_device *bd)
 	return 0;
 }
 
-static int riva_bl_update_status(struct backlight_device *bd)
-{
-	struct riva_par *par = class_get_devdata(&bd->class_dev);
-	struct fb_info *info = pci_get_drvdata(par->pdev);
-	int ret;
-
-	mutex_lock(&info->bl_mutex);
-	ret = __riva_bl_update_status(bd);
-	mutex_unlock(&info->bl_mutex);
-
-	return ret;
-}
-
 static int riva_bl_get_brightness(struct backlight_device *bd)
 {
-	return bd->props->brightness;
+	return bd->props.brightness;
 }
 
-static struct backlight_properties riva_bl_data = {
-	.owner    = THIS_MODULE,
+static struct backlight_ops riva_bl_ops = {
 	.get_brightness = riva_bl_get_brightness,
 	.update_status	= riva_bl_update_status,
-	.max_brightness = (FB_BACKLIGHT_LEVELS - 1),
 };
 
-static void riva_bl_set_power(struct fb_info *info, int power)
-{
-	mutex_lock(&info->bl_mutex);
-
-	if (info->bl_dev) {
-		down(&info->bl_dev->sem);
-		info->bl_dev->props->power = power;
-		__riva_bl_update_status(info->bl_dev);
-		up(&info->bl_dev->sem);
-	}
-
-	mutex_unlock(&info->bl_mutex);
-}
-
 static void riva_bl_init(struct riva_par *par)
 {
 	struct fb_info *info = pci_get_drvdata(par->pdev);
@@ -384,32 +354,22 @@ static void riva_bl_init(struct riva_par *par)
 
 	snprintf(name, sizeof(name), "rivabl%d", info->node);
 
-	bd = backlight_device_register(name, info->dev, par, &riva_bl_data);
+	bd = backlight_device_register(name, info->dev, par, &riva_bl_ops);
 	if (IS_ERR(bd)) {
 		info->bl_dev = NULL;
 		printk(KERN_WARNING "riva: Backlight registration failed\n");
 		goto error;
 	}
 
-	mutex_lock(&info->bl_mutex);
 	info->bl_dev = bd;
 	fb_bl_default_curve(info, 0,
 		MIN_LEVEL * FB_BACKLIGHT_MAX / MAX_LEVEL,
 		FB_BACKLIGHT_MAX);
-	mutex_unlock(&info->bl_mutex);
 
-	down(&bd->sem);
-	bd->props->brightness = riva_bl_data.max_brightness;
-	bd->props->power = FB_BLANK_UNBLANK;
-	bd->props->update_status(bd);
-	up(&bd->sem);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_lock(&pmac_backlight_mutex);
-	if (!pmac_backlight)
-		pmac_backlight = bd;
-	mutex_unlock(&pmac_backlight_mutex);
-#endif
+	bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+	bd->props.brightness = riva_bl_data.max_brightness;
+	bd->props.power = FB_BLANK_UNBLANK;
+	backlight_update_status(bd);
 
 	printk("riva: Backlight initialized (%s)\n", name);
 
@@ -419,35 +379,16 @@ error:
 	return;
 }
 
-static void riva_bl_exit(struct riva_par *par)
+static void riva_bl_exit(struct fb_info *info)
 {
-	struct fb_info *info = pci_get_drvdata(par->pdev);
+	struct backlight_device *bd = info->bl_dev;
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_lock(&pmac_backlight_mutex);
-#endif
-
-	mutex_lock(&info->bl_mutex);
-	if (info->bl_dev) {
-#ifdef CONFIG_PMAC_BACKLIGHT
-		if (pmac_backlight == info->bl_dev)
-			pmac_backlight = NULL;
-#endif
-
-		backlight_device_unregister(info->bl_dev);
-
-		printk("riva: Backlight unloaded\n");
-	}
-	mutex_unlock(&info->bl_mutex);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	mutex_unlock(&pmac_backlight_mutex);
-#endif
+	backlight_device_unregister(bd);
+	printk("riva: Backlight unloaded\n");
 }
 #else
 static inline void riva_bl_init(struct riva_par *par) {}
-static inline void riva_bl_exit(struct riva_par *par) {}
-static inline void riva_bl_set_power(struct fb_info *info, int power) {}
+static inline void riva_bl_exit(struct fb_info *info) {}
 #endif /* CONFIG_FB_RIVA_BACKLIGHT */
 
 /* ------------------------------------------------------------------------- *
@@ -1348,8 +1289,6 @@ static int rivafb_blank(int blank, struct fb_info *info)
 	SEQout(par, 0x01, tmp);
 	CRTCout(par, 0x1a, vesa);
 
-	riva_bl_set_power(info, blank);
-
 	NVTRACE_LEAVE();
 
 	return 0;
@@ -2166,14 +2105,15 @@ static void __exit rivafb_remove(struct pci_dev *pd)
 	
 	NVTRACE_ENTER();
 
-	riva_bl_exit(par);
-
 #ifdef CONFIG_FB_RIVA_I2C
 	riva_delete_i2c_busses(par);
 	kfree(par->EDID);
 #endif
 
 	unregister_framebuffer(info);
+
+	riva_bl_exit(info);
+
 #ifdef CONFIG_MTRR
 	if (par->mtrr.vram_valid)
 		mtrr_del(par->mtrr.vram, info->fix.smem_start,
diff --git a/include/linux/backlight.h b/include/linux/backlight.h
index a5cf1beacb44..1023ba0d6e55 100644
--- a/include/linux/backlight.h
+++ b/include/linux/backlight.h
@@ -9,17 +9,28 @@
 #define _LINUX_BACKLIGHT_H
 
 #include <linux/device.h>
+#include <linux/mutex.h>
 #include <linux/notifier.h>
 
+/* Notes on locking:
+ *
+ * backlight_device->ops_lock is an internal backlight lock protecting the
+ * ops pointer and no code outside the core should need to touch it.
+ *
+ * Access to update_status() is serialised by the update_lock mutex since
+ * most drivers seem to need this and historically get it wrong.
+ *
+ * Most drivers don't need locking on their get_brightness() method.
+ * If yours does, you need to implement it in the driver. You can use the
+ * update_lock mutex if appropriate.
+ *
+ * Any other use of the locks below is probably wrong.
+ */
+
 struct backlight_device;
 struct fb_info;
 
-/* This structure defines all the properties of a backlight
-   (usually attached to a LCD). */
-struct backlight_properties {
-	/* Owner module */
-	struct module *owner;
-
+struct backlight_ops {
 	/* Notify the backlight driver some property has changed */
 	int (*update_status)(struct backlight_device *);
 	/* Return the current backlight brightness (accounting for power,
@@ -28,7 +39,10 @@ struct backlight_properties {
 	/* Check if given framebuffer device is the one bound to this backlight;
 	   return 0 if not, !=0 if it is. If NULL, backlight always matches the fb. */
 	int (*check_fb)(struct fb_info *);
+};
 
+/* This structure defines all the properties of a backlight */
+struct backlight_properties {
 	/* Current User requested brightness (0 - max_brightness) */
 	int brightness;
 	/* Maximal value for brightness (read-only) */
@@ -41,20 +55,34 @@ struct backlight_properties {
 };
 
 struct backlight_device {
-	/* This protects the 'props' field. If 'props' is NULL, the driver that
+	/* Backlight properties */
+	struct backlight_properties props;
+
+	/* Serialise access to update_status method */
+	struct mutex update_lock;
+
+	/* This protects the 'ops' field. If 'ops' is NULL, the driver that
 	   registered this device has been unloaded, and if class_get_devdata()
 	   points to something in the body of that driver, it is also invalid. */
-	struct semaphore sem;
-	/* If this is NULL, the backing module is unloaded */
-	struct backlight_properties *props;
+	struct mutex ops_lock;
+	struct backlight_ops *ops;
+
 	/* The framebuffer notifier block */
 	struct notifier_block fb_notif;
 	/* The class device structure */
 	struct class_device class_dev;
 };
 
+static inline void backlight_update_status(struct backlight_device *bd)
+{
+	mutex_lock(&bd->update_lock);
+	if (bd->ops && bd->ops->update_status)
+		bd->ops->update_status(bd);
+	mutex_unlock(&bd->update_lock);
+}
+
 extern struct backlight_device *backlight_device_register(const char *name,
-	struct device *dev,void *devdata,struct backlight_properties *bp);
+	struct device *dev, void *devdata, struct backlight_ops *ops);
 extern void backlight_device_unregister(struct backlight_device *bd);
 
 #define to_backlight_device(obj) container_of(obj, struct backlight_device, class_dev)
diff --git a/include/linux/fb.h b/include/linux/fb.h
index a78e25683f82..be913ec87169 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -516,13 +516,15 @@ struct fb_cursor_user {
 #define FB_EVENT_GET_CONSOLE_MAP        0x07
 /*      CONSOLE-SPECIFIC: set console to framebuffer mapping */
 #define FB_EVENT_SET_CONSOLE_MAP        0x08
-/*      A display blank is requested       */
+/*      A hardware display blank change occured */
 #define FB_EVENT_BLANK                  0x09
 /*      Private modelist is to be replaced */
 #define FB_EVENT_NEW_MODELIST           0x0A
 /*	The resolution of the passed in fb_info about to change and
         all vc's should be changed         */
 #define FB_EVENT_MODE_CHANGE_ALL	0x0B
+/*	A software display blank change occured */
+#define FB_EVENT_CONBLANK               0x0C
 
 struct fb_event {
 	struct fb_info *info;
@@ -767,16 +769,13 @@ struct fb_info {
 	struct fb_videomode *mode;	/* current mode */
 
 #ifdef CONFIG_FB_BACKLIGHT
-	/* Lock ordering:
-	 * bl_mutex (protects bl_dev and bl_curve)
-	 *   bl_dev->sem (backlight class)
-	 */
-	struct mutex bl_mutex;
-
 	/* assigned backlight device */
+	/* set before framebuffer registration, 
+	   remove after unregister */
 	struct backlight_device *bl_dev;
 
 	/* Backlight level curve */
+	struct mutex bl_curve_mutex;	
 	u8 bl_curve[FB_BACKLIGHT_LEVELS];
 #endif
 
diff --git a/include/linux/lcd.h b/include/linux/lcd.h
index d739b2e7eac2..598793c0745b 100644
--- a/include/linux/lcd.h
+++ b/include/linux/lcd.h
@@ -9,22 +9,38 @@
 #define _LINUX_LCD_H
 
 #include <linux/device.h>
+#include <linux/mutex.h>
 #include <linux/notifier.h>
 
+/* Notes on locking:
+ *
+ * lcd_device->ops_lock is an internal backlight lock protecting the ops
+ * field and no code outside the core should need to touch it.
+ *
+ * Access to set_power() is serialised by the update_lock mutex since
+ * most drivers seem to need this and historically get it wrong.
+ *
+ * Most drivers don't need locking on their get_power() method.
+ * If yours does, you need to implement it in the driver. You can use the
+ * update_lock mutex if appropriate.
+ *
+ * Any other use of the locks below is probably wrong.
+ */
+
 struct lcd_device;
 struct fb_info;
 
-/* This structure defines all the properties of a LCD flat panel. */
 struct lcd_properties {
-	/* Owner module */
-	struct module *owner;
+	/* The maximum value for contrast (read-only) */
+	int max_contrast;
+};
+
+struct lcd_ops {
 	/* Get the LCD panel power status (0: full on, 1..3: controller
 	   power on, flat panel power off, 4: full off), see FB_BLANK_XXX */
 	int (*get_power)(struct lcd_device *);
 	/* Enable or disable power to the LCD (0: on; 4: off, see FB_BLANK_XXX) */
 	int (*set_power)(struct lcd_device *, int power);
-	/* The maximum value for contrast (read-only) */
-	int max_contrast;
 	/* Get the current contrast setting (0-max_contrast) */
 	int (*get_contrast)(struct lcd_device *);
 	/* Set LCD panel contrast */
@@ -35,20 +51,31 @@ struct lcd_properties {
 };
 
 struct lcd_device {
-	/* This protects the 'props' field. If 'props' is NULL, the driver that
+	struct lcd_properties props;
+	/* This protects the 'ops' field. If 'ops' is NULL, the driver that
 	   registered this device has been unloaded, and if class_get_devdata()
 	   points to something in the body of that driver, it is also invalid. */
-	struct semaphore sem;
+	struct mutex ops_lock;
 	/* If this is NULL, the backing module is unloaded */
-	struct lcd_properties *props;
+	struct lcd_ops *ops;
+	/* Serialise access to set_power method */
+	struct mutex update_lock;
 	/* The framebuffer notifier block */
 	struct notifier_block fb_notif;
 	/* The class device structure */
 	struct class_device class_dev;
 };
 
+static inline void lcd_set_power(struct lcd_device *ld, int power)
+{
+	mutex_lock(&ld->update_lock);
+	if (ld->ops && ld->ops->set_power)
+		ld->ops->set_power(ld, power);
+	mutex_unlock(&ld->update_lock);
+}
+
 extern struct lcd_device *lcd_device_register(const char *name,
-	void *devdata, struct lcd_properties *lp);
+	void *devdata, struct lcd_ops *ops);
 extern void lcd_device_unregister(struct lcd_device *ld);
 
 #define to_lcd_device(obj) container_of(obj, struct lcd_device, class_dev)