提交 a5527c6a 编写于 作者: L Linus Torvalds

Merge branch 'for-linus' of git://git.o-hand.com/linux-rpurdie-backlight

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