GIT 8dc7a6f254f7c8a6f19043aa09411eca1e2e0168 git://git.o-hand.com/linux-rpurdie-backlight#for-mm commit Author: Michael Hanselmann Date: Sat Feb 10 23:54:22 2007 +0000 backlight: Fix null pointer dereference in appledisplay driver Commit 40b20c257a13c5a526ac540bc5e43d0fdf29792a by Len Brown introduced a null pointer dereference in the appledisplay driver. This patch fixes it. Signed-off-by: Michael Hanselmann Signed-off-by: Andrew Morton Signed-off-by: Richard Purdie commit 065e3e2265c5a88c45368826f10d9c45d3010a71 Author: Richard Purdie Date: Sat Feb 10 23:50:39 2007 +0000 backlight: simplify corgi_bl locking Now update_status has locking, we can remove the mutex from corgi_bl. Signed-off-by: Richard Purdie commit 034e89c0cdd2176351308fb84a143f3aa7aac74d Author: Richard Purdie Date: Sat Feb 10 23:07:48 2007 +0000 backlight: Separate backlight properties from backlight ops pointers Per device data such as brightness belongs to the indivdual device and should therefore be separate from the the backlight operation function pointers. This patch splits the two types of data and allows simplifcation of some code. Signed-off-by: Richard Purdie commit c86fe9a5bbd0e7fce5e2d85c37f6ff83a30829f1 Author: Richard Purdie Date: Sat Feb 10 15:04:08 2007 +0000 backlight: Clean up pmac_backlight handling Move the setting/unsetting of pmac_backlight into the backlight core instead of doing it in each driver. Signed-off-by: Richard Purdie commit 4920521256dda77c2222df19a383ad995c58437c Author: James Simmons Date: Sat Feb 10 14:15:43 2007 +0000 backlight: Improve backlight selection for fbdev drivers Improve backlight selection for fbdev drivers Signed-off-by: James Simmons Signed-off-by: Andrew Morton Signed-off-by: Richard Purdie commit 41203208b412f477811e2e0e84a69c669fe72f8c Author: Richard Purdie Date: Sat Feb 10 14:10:33 2007 +0000 backlight: Rework backlight/fb interaction simplifying, lots fb_info->bl_mutex is badly thought out and the backlight class doesn't need it if the framebuffer/backlight register/unregister order is consistent, particularly after the backlight locking fixes. Fix the drivers to use the order: backlight_device_register() register_framebuffer() unregister_framebuffer() backlight_device_unregister() and turn bl_mutex into a lock for the bl_curve data only. Signed-off-by: Richard Purdie commit 5ee822756ce9683f75581b40055c5c473eff36cb Author: Richard Purdie Date: Fri Feb 9 09:53:56 2007 +0000 backlight: Remove unneeded backlight update_status calls The backlight core listens for blanking events and triggers a backlight_update_status call so these extra calls are not needed and can be removed. Signed-off-by: Richard Purdie commit f274ad3c613476632a8bf5a5fb89f4417bb49181 Author: Richard Purdie Date: Fri Feb 9 09:50:47 2007 +0000 backlight: Remove uneeded update_status call from chipsfb.c Remove uneeded update_status call from chipsfb.c since the backlight core now receives software blanking notifications too. Signed-off-by: Richard Purdie commit 01d90602f9718ae73d577fdc40f67ec4a9f3f81b Author: Richard Purdie Date: Fri Feb 9 09:46:45 2007 +0000 backlight/fbcon: Add FB_EVENT_CONBLANK The backlight class wants notification whenever the console is blanked but doesn't get this when hardware blanking fails and software blanking is used. Changing FB_EVENT_BLANK to report both would be a behaviour change which could confuse the console layer so add a new event for software blanking and have the backlight class listen for both. Signed-off-by: Richard Purdie commit d5be014680224bacd2fdb9803d366cacd657ca60 Author: Richard Purdie Date: Fri Feb 9 09:40:30 2007 +0000 backlight: Fix Kconfig entries Currently its possible to build the backlight core as a module yet compile the drivers into the kernel which gives missing symbols. Fix. Signed-off-by: Richard Purdie commit a442c5f77e8a99c05b2c96955fb752b11ab32901 Author: Richard Purdie Date: Fri Feb 9 00:34:52 2007 +0000 backlight: Remove uneeded nvidia set_power calls nvidia_bl_set_power isn't needed since the backlight class handles this by receiving fb events itself and calling update_status so remove it. Signed-off-by: Richard Purdie commit d5711961bafe9d23038cfe033e1ba9bd55df1325 Author: Richard Purdie Date: Thu Feb 8 22:53:55 2007 +0000 backlight: Convert semaphore -> mutex Convert internal semaphore to a mutex Signed-off-by: Richard Purdie commit 7f4ff8437c121927fa871a44c076b719885c64aa Author: Richard Purdie Date: Thu Feb 8 22:25:09 2007 +0000 backlight: Fix external uses of backlight internal semaphore backlight_device->sem has a very specific use as documented in the header file. The external users of this are using it for a different reason, to serialise access to the update_status() method. backlight users were supposed to implement their own internal serialisation of update_status() if needed but everyone is doing things differently and incorrectly. Therefore add a global mutex to take care of serialisation for everyone, once and for all. Locking for get_brightness remains optional since most users don't need it. Also update the lcd class in a similar way. Signed-off-by: Richard Purdie commit 91ccaabb98af7262bf28f85d084130a5f9885651 Author: Richard Purdie Date: Thu Feb 8 00:33:24 2007 +0000 backlight: Minor code cleanups for hp680_bl.c Since people use this code as an example, clean it up to to use platform_*_drvdata instead of a global variable. Signed-off-by: Richard Purdie commit 85b94c06fef1149f2930358d44f705b0f3d43ba3 Author: Richard Purdie Date: Thu Feb 8 00:32:14 2007 +0000 backlight: Minor code cleanups for corgi_bl.c Since people use this code as an example, clean it up to to use platform_*_drvdata and remove an unneeded function. Signed-off-by: Richard Purdie commit 1c7f8f2f530199f6c61e1d269d2376ec73969aa3 Author: Dmitry Torokhov Date: Thu Feb 8 00:12:28 2007 +0000 backlight: Remove excessive (un)likelys Remove excessive numbers of (un)likely()s in the backlight core. There are no hot paths in this code so rely on compiler to do the right thing. Signed-off-by: Dmitry Torokhov Signed-off-by: Richard Purdie commit 2d788f231df341fe4dcea1274dc6375efe3e800b Author: Richard Purdie Date: Thu Feb 8 00:06:32 2007 +0000 backlight: Remove unneeded owner field Remove uneeded owner field from backlight_properties structure. Nothing uses it and it is unlikely that it will ever be used. The backlight class uses other means to ensure that nothing references unloaded code. Based on a patch from Dmitry Torokhov Signed-off-by: Richard Purdie commit 981f961e8263913256f28bfffbb7e5872c643267 Author: Dmitry Torokhov Date: Wed Feb 7 22:25:50 2007 +0000 backlight: Fix error handling Fix error handling when registering new device Signed-off-by: Dmitry Torokhov Signed-off-by: Richard Purdie commit cd27b3bd4d192657a410d6d21525201f3845ba91 Author: Marcin Juszkiewicz Date: Wed Feb 7 22:24:01 2007 +0000 backlight: Add Frontpath ProGear HX1050+ driver Add control of LCD backlight for Frontpath ProGear HX1050+. Patch is based on http://downloads.sf.net/progear/progear-lcd-0.2.tar.gz driver by M Schacht. Signed-off-by: Marcin Juszkiewicz Signed-off-by: Richard Purdie commit 176b9be72e73bf22a3cf1e6a915d2cdfb9be307a Author: Richard Purdie Date: Wed Feb 7 22:21:07 2007 +0000 backlight: Add maintainer entry Add myself as the backlight class/subsystem maintainer. Signed-off-by: Richard Purdie MAINTAINERS | 5 + arch/powerpc/kernel/traps.c | 6 - arch/powerpc/platforms/powermac/backlight.c | 27 ++--- drivers/acpi/asus_acpi.c | 7 + drivers/acpi/ibm_acpi.c | 8 + drivers/acpi/toshiba_acpi.c | 7 + drivers/acpi/video.c | 36 ++---- drivers/macintosh/via-pmu-backlight.c | 33 ++---- drivers/misc/asus-laptop.c | 31 ++--- drivers/misc/msi-laptop.c | 10 +- drivers/usb/misc/appledisplay.c | 18 +-- drivers/video/Kconfig | 73 ++++++------- drivers/video/aty/aty128fb.c | 102 +++--------------- drivers/video/aty/atyfb_base.c | 100 +++--------------- drivers/video/aty/radeon_backlight.c | 59 ++-------- drivers/video/aty/radeon_base.c | 3 - drivers/video/backlight/Kconfig | 24 ++-- drivers/video/backlight/Makefile | 1 drivers/video/backlight/backlight.c | 123 +++++++++++----------- drivers/video/backlight/corgi_bl.c | 54 +++++----- drivers/video/backlight/hp680_bl.c | 50 +++++---- drivers/video/backlight/lcd.c | 83 +++++++-------- drivers/video/backlight/locomolcd.c | 13 +- drivers/video/backlight/progear_bl.c | 153 +++++++++++++++++++++++++++ drivers/video/chipsfb.c | 26 ----- drivers/video/console/fbcon.c | 7 + drivers/video/fbsysfs.c | 14 ++ drivers/video/nvidia/nv_backlight.c | 92 +++------------- drivers/video/nvidia/nv_proto.h | 2 drivers/video/nvidia/nvidia.c | 5 - drivers/video/riva/fbdev.c | 100 ++++-------------- include/linux/backlight.h | 50 +++++++-- include/linux/fb.h | 13 +- include/linux/lcd.h | 45 ++++++-- 34 files changed, 622 insertions(+), 758 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 9e6c9ff..a54a140 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -666,6 +666,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 dcc6f15..17724fb 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -107,12 +107,10 @@ #ifdef CONFIG_PMAC_BACKLIGHT 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 c3a8941..de7440e 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_que */ 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(st 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(st 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_b 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_b 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 31ad70a..c251133 100644 --- a/drivers/acpi/asus_acpi.c +++ b/drivers/acpi/asus_acpi.c @@ -838,7 +838,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 @@ -1340,11 +1340,9 @@ static int asus_hotk_remove(struct acpi_ 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) @@ -1402,6 +1400,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 c6144ca..620afe5 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -1697,14 +1697,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) @@ -1716,6 +1714,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 d9b651f..ba92c9b 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( 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) @@ -601,6 +599,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 e0b97ad..48dbec4 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -170,7 +170,6 @@ struct acpi_video_device { struct acpi_device *dev; struct acpi_video_device_brightness *brightness; struct backlight_device *backlight; - struct backlight_properties *data; }; /* bus */ @@ -287,13 +286,18 @@ static int acpi_video_get_brightness(str 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 -------------------------------------------------------------------------- */ @@ -609,31 +613,18 @@ static void acpi_video_device_find_cap(s 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; @@ -1678,10 +1669,7 @@ static int acpi_video_bus_put_one_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 801a974..7e27071 100644 --- a/drivers/macintosh/via-pmu-backlight.c +++ b/drivers/macintosh/via-pmu-backlight.c @@ -15,7 +15,7 @@ #include #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(s { 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(s 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 861c399..3c82664 100644 --- a/drivers/misc/asus-laptop.c +++ b/drivers/misc/asus-laptop.c @@ -195,11 +195,9 @@ static struct backlight_device *asus_bac */ 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 backlig 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 de 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 de 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 8e5e07e..68c4b58 100644 --- a/drivers/misc/msi-laptop.c +++ b/drivers/misc/msi-laptop.c @@ -157,14 +157,12 @@ static int bl_get_brightness(struct back 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/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index 32f0e3a..f63fed3 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -141,7 +141,7 @@ static int appledisplay_bl_update_status 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_brightnes 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 wor 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 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 } /* 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 8874cf2..cd2ef0a 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -4,20 +4,9 @@ # 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. +if SYSFS + source "drivers/video/backlight/Kconfig" +endif config FB tristate "Support for frame buffer devices" @@ -53,9 +42,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 +141,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 +681,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 +710,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 +718,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 +756,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 +806,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 +995,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 +1026,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 +1046,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 +1058,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 +1069,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 +1108,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 +1127,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 +1641,7 @@ config FB_VIRTUAL the vfb_enable=1 option. If unsure, say N. + if VT source "drivers/video/console/Kconfig" endif @@ -1647,9 +1650,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/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 2e976ff..8726c36 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -1695,9 +1695,6 @@ #endif /* MODULE */ #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_brightnes 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 @@ #define BACKLIGHT_LVDS_OFF /* 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 @@ #endif 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 @@ #endif 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(stru 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, str 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 @@ #endif 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 301612c..a7e0062 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -2114,15 +2114,13 @@ #endif /* defined(CONFIG_PM) && defined #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(s 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 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 @@ #endif 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 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 @@ #endif 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(struc 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 3abfd4a..0be25fa 100644 --- a/drivers/video/aty/radeon_backlight.c +++ b/drivers/video/aty/radeon_backlight.c @@ -19,8 +19,6 @@ #endif #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(struc * 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(struc 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 @@ #ifdef CONFIG_PMAC_BACKLIGHT 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 0ed577e..7e228ad 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -2393,7 +2393,6 @@ static void __devexit radeonfb_pci_unreg if (!rinfo) return; - radeonfb_bl_exit(rinfo); radeonfb_pm_exit(rinfo); if (rinfo->mon1_EDID) @@ -2420,6 +2419,8 @@ #endif 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 02f1529..b51191a 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,17 @@ 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 y + 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 65e5553..0c3ce46 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += 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 9601bfe..c65e81f 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -14,6 +14,9 @@ #include #include #include +#ifdef CONFIG_PMAC_BACKLIGHT +#include +#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 n 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 @@ #endif /* CONFIG_FB */ 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(str 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_brightnes 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_bri 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_attribu * 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_attribu 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 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 fde1d95..ce00e18 100644 --- a/drivers/video/backlight/corgi_bl.c +++ b/drivers/video/backlight/corgi_bl.c @@ -22,7 +22,6 @@ #include #include 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 @@ #define CORGIBL_BATTLOW 0x02 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 } #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 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 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 c07d820..0899fcc 100644 --- a/drivers/video/backlight/hp680_bl.c +++ b/drivers/video/backlight/hp680_bl.c @@ -28,17 +28,16 @@ #define HP680_DEFAULT_INTENSITY 10 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(struc #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 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; + + bd = backlight_device_register ("hp680-bl", &pdev->dev, NULL, + &hp680bl_ops); + if (IS_ERR(bd)) + return PTR_ERR(bd); - hp680_backlight_device->props->brightness = HP680_DEFAULT_INTENSITY; - hp680bl_send_intensity(hp680_backlight_device); + 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 f6e0416..6ef8f0a 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -31,11 +31,11 @@ static int fb_notifier_callback(struct n 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 cla 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 cl 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 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 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_attribu * 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_de 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 fc812d9..d131247 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(struc 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 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 0000000..7022693 --- /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 + * + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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 "); +MODULE_DESCRIPTION("ProGear Backlight Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c index 73cb426..af313bf 100644 --- a/drivers/video/chipsfb.c +++ b/drivers/video/chipsfb.c @@ -145,26 +145,6 @@ static int chipsfb_set_par(struct fb_inf 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 @@ #ifdef CONFIG_PMAC_BACKLIGHT /* 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 be3f2c3..0429fd2 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -2233,6 +2233,8 @@ static int fbcon_switch(struct vc_data * 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 v fbcon_clear(vc, 0, 0, vc->vc_rows, vc->vc_cols); vc->vc_video_erase_char = oldc; } + + + event.info = info; + event.data = ␣ + 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 818fb09..40c80c8 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c @@ -59,7 +59,7 @@ #define PADDING (BYTES_PER_LONG - (sizeo 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 dev /* 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 devi 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 devi 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 { 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 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 df934bd..b7016e9 100644 --- a/drivers/video/nvidia/nv_backlight.c +++ b/drivers/video/nvidia/nv_backlight.c @@ -16,11 +16,6 @@ #include "nv_local.h" #include "nv_type.h" #include "nv_proto.h" -#ifdef CONFIG_PMAC_BACKLIGHT -#include -#include -#endif - /* We do not have any information about which values are allowed, thus * we used safe values. */ @@ -30,7 +25,6 @@ #define LEVEL_STEP ((MAX_LEVEL - MIN_LEV 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_brightnes 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_brightnes 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(str 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(str 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 @@ #endif 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 43058d0..ff5c410 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 #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 8e5b484..c18e955 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -938,8 +938,6 @@ static int nvidiafb_blank(int blank, str 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(st 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 f2e9b74..f8a3d60 100644 --- a/drivers/video/riva/fbdev.c +++ b/drivers/video/riva/fbdev.c @@ -282,7 +282,6 @@ #define LEVEL_STEP ((MAX_LEVEL - MIN_LEV 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( 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( 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(struc 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 @@ #endif 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); - -#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 + struct backlight_device *bd = info->bl_dev; - 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, struc 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 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 a5cf1be..1023ba0 100644 --- a/include/linux/backlight.h +++ b/include/linux/backlight.h @@ -9,17 +9,28 @@ #ifndef _LINUX_BACKLIGHT_H #define _LINUX_BACKLIGHT_H #include +#include #include +/* 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 a78e256..be913ec 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -516,13 +516,15 @@ #define FB_EVENT_FB_UNREGISTERED #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 d739b2e..598793c 100644 --- a/include/linux/lcd.h +++ b/include/linux/lcd.h @@ -9,22 +9,38 @@ #ifndef _LINUX_LCD_H #define _LINUX_LCD_H #include +#include #include +/* 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)