I changed a little the source so it can compile against a 2.6.34 kernel. The changes were copied from MacTel Team latest module (
). Change the .min and .max values to fit your hardware and add the pci id to "static DEFINE_PCI_DEVICE_TABLE(nvidia_bl_device_table)" section accordingly from
if your card is not already there.
P.S. It will compile only against a 2.6.34 kernel. For a previous kernel use the original source from guillaumezin in the first post.
Code:
/*
* Backlight driver for Nvidia graphics adapters.
*
* Copyright (c) 2008-2009 Mario Schwalbe <schwalbe@inf.tu-dresden.de>
* Based on the mechanism dicovered by the author of NvClock:
* Copyright (c) 2001-2009 Roderick Colenbrander
* Site: http://nvclock.sourceforge.net
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
/*
* Maybe the check against the subsystem vendor should be removed,
* but there's no guarantee that the chip's smartdimmer signals
* are actually connected to the display logic. Right now, these
* are the supported (read connected) vendors according to NvClock.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/backlight.h>
#include <linux/dmi.h>
#include <linux/pci.h>
#include <linux/err.h>
#include <linux/fb.h>
/* Check for the new backlight suspend/resume feature */
#if defined(BL_CORE_SUSPENDRESUME)
#warning USE_BACKLIGHT_SUSPEND
#define USE_BACKLIGHT_SUSPEND
/* Otherwise use a platform driver if PM is enabled */
#elif defined(CONFIG_PM)
#warning USE_PLATFORM_DRIVER
#define USE_PLATFORM_DRIVER
#endif
/* Register constants */
#define INIT_BACKLIGHT_PROPS
#define NV5X_PDISPLAY_OFFSET 0x00610000
#define NV5X_PDISPLAY_SOR0_BRIGHTNESS 0x0000c084
#define NV5X_PDIPSLAY_SOR0_BRIGHTNESS_CONTROL_ENABLED 0x80000000
/* Driver private data structure */
struct driver_data {
/* PCI region (BAR) the smartdimmer register is in */
unsigned bar;
/* Register offset into this region */
unsigned long reg_offset;
/* Register size in byte */
unsigned reg_size;
/* off, min and max value for intensity in register */
unsigned off, min, max;
/* Backlight operations structure */
struct backlight_ops backlight_ops;
/* The device we drive */
struct pci_dev *dev;
/* Pointer to the mapped smartdimmer register */
/* volatile */ void __iomem *smartdimmer;
};
static unsigned int nvidia_bl_ignore_device = 0;
static unsigned long pci_id = PCI_ANY_ID;
static inline unsigned int get_intensity(unsigned int reg_value, int off, int min, int max) {
if (reg_value == off)
return 0;
else
return (reg_value - min) * (FB_BACKLIGHT_LEVELS - 1) / (max - min);
}
static inline unsigned int set_intensity(unsigned int intensity, int off, int min, int max, int forceoff) {
if (forceoff)
return off;
else
return min + (intensity * (max - min) / (FB_BACKLIGHT_LEVELS - 1));
}
/*
* Implementation for NV4X chips
* (NV40, NV41, NV43, NV44, NV46, NV47, NV49, NV4B, C51)
*/
static int nv4x_get_intensity(struct backlight_device *bd)
{
struct driver_data *dd = bl_get_data(bd);
unsigned short intensity = ioread16(dd->smartdimmer) & 0x1f;
intensity = get_intensity(intensity, dd->off, dd->min, dd->max);
return intensity;
}
static int nv4x_set_intensity(struct backlight_device *bd)
{
struct driver_data *dd = bl_get_data(bd);
unsigned intensity;
intensity = set_intensity(
bd->props.brightness,
dd->off,
dd->min,
dd->max,
(bd->props.power != FB_BLANK_UNBLANK || bd->props.fb_blank != FB_BLANK_UNBLANK)
);
iowrite16((ioread16(dd->smartdimmer) & ~0x1f) | intensity,
dd->smartdimmer);
return 0;
}
static struct driver_data nv4x_driver_data = {
.bar = 0,
.reg_offset = 0x15f2,
.reg_size = 2,
.off = 0,
.min = 4,
.max = 21,
.backlight_ops = {
#ifdef USE_BACKLIGHT_SUSPEND
.options = BL_CORE_SUSPENDRESUME,
#endif
.get_brightness = nv4x_get_intensity,
.update_status = nv4x_set_intensity,
}
};
/*
* Implementation for NV5X chips
* (NV50, G84, G86, G92, G94, G96, GT200)
*/
static int nv5x_get_intensity(struct backlight_device *bd)
{
struct driver_data *dd = bl_get_data(bd);
unsigned intensity = ioread32(dd->smartdimmer) &
~NV5X_PDIPSLAY_SOR0_BRIGHTNESS_CONTROL_ENABLED;
intensity = get_intensity(intensity, dd->off, dd->min, dd->max);
return intensity;
}
static int nv5x_set_intensity(struct backlight_device *bd)
{
struct driver_data *dd = bl_get_data(bd);
unsigned intensity;
intensity = set_intensity(
bd->props.brightness,
dd->off,
dd->min,
dd->max,
(bd->props.power != FB_BLANK_UNBLANK || bd->props.fb_blank != FB_BLANK_UNBLANK)
);
iowrite32(intensity | NV5X_PDIPSLAY_SOR0_BRIGHTNESS_CONTROL_ENABLED,
dd->smartdimmer);
return 0;
}
static struct driver_data nv5x_driver_data = {
.bar = 0,
.reg_offset = NV5X_PDISPLAY_OFFSET + NV5X_PDISPLAY_SOR0_BRIGHTNESS,
.reg_size = 4,
.off = 0,
.min = 1024,
.max = 140000,
.backlight_ops = {
#ifdef USE_BACKLIGHT_SUSPEND
.options = BL_CORE_SUSPENDRESUME,
#endif
.get_brightness = nv5x_get_intensity,
.update_status = nv5x_set_intensity,
}
};
/*
* Device matching.
* The list of supported devices was primarily taken from NvClock,
* but only contains the mobile chips.
*/
static DEFINE_PCI_DEVICE_TABLE(nvidia_bl_device_table) = {
/* nVidia Geforce Go 7800GTX */
{ PCI_VDEVICE(NVIDIA, 0x0099), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia Geforce Go 6800 */
{ PCI_VDEVICE(NVIDIA, 0x00c8), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia Geforce Go 6800Ultra */
{ PCI_VDEVICE(NVIDIA, 0x00c9), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia QuadroFX Go 1400 */
{ PCI_VDEVICE(NVIDIA, 0x00cc), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia Geforce Go 6600 */
{ PCI_VDEVICE(NVIDIA, 0x0144), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia GeForce Go 6600TE/6200TE */
{ PCI_VDEVICE(NVIDIA, 0x0146), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia Geforce Go 6600 */
{ PCI_VDEVICE(NVIDIA, 0x0148), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia Geforce Go 6600GT */
{ PCI_VDEVICE(NVIDIA, 0x0149), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia Geforce Go 6200 */
{ PCI_VDEVICE(NVIDIA, 0x0164), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia Geforce Go 6400 */
{ PCI_VDEVICE(NVIDIA, 0x0166), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia Geforce Go 6200 */
{ PCI_VDEVICE(NVIDIA, 0x0167), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia Geforce Go 6400 */
{ PCI_VDEVICE(NVIDIA, 0x0168), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia Geforce Go 7300 */
{ PCI_VDEVICE(NVIDIA, 0x01d7), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia Geforce Go 7400 */
{ PCI_VDEVICE(NVIDIA, 0x01d8), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia Geforce Go 7400GS */
{ PCI_VDEVICE(NVIDIA, 0x01d9), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia Quadro NVS 110M */
{ PCI_VDEVICE(NVIDIA, 0x01da), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia Quadro NVS 120M */
{ PCI_VDEVICE(NVIDIA, 0x01db), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia QuadroFX 350M */
{ PCI_VDEVICE(NVIDIA, 0x01dc), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia Geforce 7500LE */
{ PCI_VDEVICE(NVIDIA, 0x01dd), (kernel_ulong_t)&nv4x_driver_data },
/* NV44M */
{ PCI_VDEVICE(NVIDIA, 0x0228), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia Geforce Go 7950GTX */
{ PCI_VDEVICE(NVIDIA, 0x0297), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia Geforce Go 7900GS */
{ PCI_VDEVICE(NVIDIA, 0x0298), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia Geforce Go 7900GTX */
{ PCI_VDEVICE(NVIDIA, 0x0299), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia QuadroFX 2500M */
{ PCI_VDEVICE(NVIDIA, 0x029a), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia QuadroFX 1500M */
{ PCI_VDEVICE(NVIDIA, 0x029b), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia Geforce Go 7700 */
{ PCI_VDEVICE(NVIDIA, 0x0397), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia Geforce Go 7600 */
{ PCI_VDEVICE(NVIDIA, 0x0398), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia Geforce Go 7600GT */
{ PCI_VDEVICE(NVIDIA, 0x0399), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia Quadro NVS 300M */
{ PCI_VDEVICE(NVIDIA, 0x039a), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia Geforce Go 7900SE */
{ PCI_VDEVICE(NVIDIA, 0x039b), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia QuadroFX 550M */
{ PCI_VDEVICE(NVIDIA, 0x039c), (kernel_ulong_t)&nv4x_driver_data },
/* nVidia Geforce 9500M GS */
{ PCI_VDEVICE(NVIDIA, 0x0405), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Geforce NB9P-GE */
{ PCI_VDEVICE(NVIDIA, 0x0406), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Geforce 8600M GT */
{ PCI_VDEVICE(NVIDIA, 0x0407), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Geforce 8600M GTS */
{ PCI_VDEVICE(NVIDIA, 0x0408), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Geforce 8700M GT */
{ PCI_VDEVICE(NVIDIA, 0x0409), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Quadro NVS 370M */
{ PCI_VDEVICE(NVIDIA, 0x040a), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Quadro NVS 320M */
{ PCI_VDEVICE(NVIDIA, 0x040b), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia QuadroFX 570M */
{ PCI_VDEVICE(NVIDIA, 0x040c), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia QuadroFX 1600M */
{ PCI_VDEVICE(NVIDIA, 0x040d), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Geforce 8600M GS */
{ PCI_VDEVICE(NVIDIA, 0x0425), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Geforce 8400M GT */
{ PCI_VDEVICE(NVIDIA, 0x0426), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Geforce 8400M GS */
{ PCI_VDEVICE(NVIDIA, 0x0427), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Geforce 8400M G */
{ PCI_VDEVICE(NVIDIA, 0x0428), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Quadro NVS 140M */
{ PCI_VDEVICE(NVIDIA, 0x0429), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Quadro NVS 130M */
{ PCI_VDEVICE(NVIDIA, 0x042a), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Quadro NVS 135M */
{ PCI_VDEVICE(NVIDIA, 0x042b), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Quadro FX 360M */
{ PCI_VDEVICE(NVIDIA, 0x042d), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Geforce 9300M G */
{ PCI_VDEVICE(NVIDIA, 0x042e), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Geforce 8800M GTS */
{ PCI_VDEVICE(NVIDIA, 0x0609), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Geforce 8800M GTX */
{ PCI_VDEVICE(NVIDIA, 0x060c), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia QuadroFX 3600M */
{ PCI_VDEVICE(NVIDIA, 0x061c), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Geforce 9600M GT */
{ PCI_VDEVICE(NVIDIA, 0x0647), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Geforce 9600M GS */
{ PCI_VDEVICE(NVIDIA, 0x0648), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Geforce 9600M GT */
{ PCI_VDEVICE(NVIDIA, 0x0649), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Geforce 9500M G */
{ PCI_VDEVICE(NVIDIA, 0x064b), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Geforce 9300M GS */
{ PCI_VDEVICE(NVIDIA, 0x06e5), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Geforce 9200M GS */
{ PCI_VDEVICE(NVIDIA, 0x06e8), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Geforce 9300M GS */
{ PCI_VDEVICE(NVIDIA, 0x06e9), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Quadro NVS 150M */
{ PCI_VDEVICE(NVIDIA, 0x06ea), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Quadro NVS 160M */
{ PCI_VDEVICE(NVIDIA, 0x06eb), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Geforce G105M */
{ PCI_VDEVICE(NVIDIA, 0x06ec), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia QuadroFX 370M */
{ PCI_VDEVICE(NVIDIA, 0x06fb), (kernel_ulong_t)&nv5x_driver_data },
/* nVidia Geforce 9400M */
{ PCI_VDEVICE(NVIDIA, 0x0863), (kernel_ulong_t)&nv5x_driver_data },
/* NVIDIA GeForce 9400M */
{ PCI_VDEVICE(NVIDIA, 0x0870), (kernel_ulong_t)&nv5x_driver_data },
/* NVIDIA GeForce 9200 */
{ PCI_VDEVICE(NVIDIA, 0x0871), (kernel_ulong_t)&nv5x_driver_data },
/* NVIDIA GeForce G102M */
{ PCI_VDEVICE(NVIDIA, 0x0872), (kernel_ulong_t)&nv5x_driver_data },
/* NVIDIA GeForce G102M */
{ PCI_VDEVICE(NVIDIA, 0x0873), (kernel_ulong_t)&nv5x_driver_data },
/* NVIDIA GeForce GT 230M */
{ PCI_VDEVICE(NVIDIA, 0x0A2A), (kernel_ulong_t)&nv5x_driver_data },
/* end of list */
{ }
};
/*
* DMI matching.
* Used to ignore the wrong device on machines incorporating 2
* graphics adapters, such as the Apple MacBook Pro 5.
*/
static int nvidia_bl_wrong_dmi_match(const struct dmi_system_id *id)
{
printk(KERN_INFO "nvidia_bl: %s model detected in ignore tables\n", id->ident);
nvidia_bl_ignore_device = (unsigned long)id->driver_data;
return 1;
}
static const struct dmi_system_id /* __initdata */ nvidia_bl_ignore_table[] = {
{
.callback = &nvidia_bl_wrong_dmi_match,
.ident = "MacBookPro 5,1",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,1"),
},
.driver_data = (void *)0x0863, /* nVidia Geforce 9400M */
},
{
.callback = &nvidia_bl_wrong_dmi_match,
.ident = "MacBookPro 5,2",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,2"),
},
.driver_data = (void *)0x0863, /* nVidia Geforce 9400M */
},
{
.callback = &nvidia_bl_wrong_dmi_match,
.ident = "MacBookPro 5,5",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,5"),
},
.driver_data = (void *)0x0863, /* nVidia Geforce 9400M */
},
/* end of list */
{ }
};
/*
* DMI matching.
* Used to autoload driver
*/
static int nvidia_bl_dmi_match(const struct dmi_system_id *id)
{
printk(KERN_INFO "nvidia_bl: %s model detected in DMI tables\n", id->ident);
pci_id = (unsigned long)id->driver_data;
return 1;
}
static const struct dmi_system_id /* __initdata */ nvidia_bl_dmi_table[] = {
{
.callback = &nvidia_bl_dmi_match,
.ident = "VGN-AW11",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "VGN-AW11"),
},
.driver_data = (void *)0x06e9, /* nVidia Geforce 9300M GS - obtained from lspci -nn */
},
{
.callback = &nvidia_bl_dmi_match,
.ident = "VGN-FZ11",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ11"),
},
.driver_data = (void *)0x0426, /* nVidia Geforce 8400M GS - obtained from lspci -nn */
},
{
.callback = &nvidia_bl_dmi_match,
.ident = "VGN-FZ38",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ38"),
},
.driver_data = (void *)0x0426, /* nVidia Geforce 8400M GS - obtained from lspci -nn */
},
/* end of list */
{ }
};
/*
* Driver data implementation
*/
static const struct pci_device_id *nvidia_bl_match_id(struct pci_dev *dev)
{
/* Search id in table */
const struct pci_device_id *id = pci_match_id(nvidia_bl_device_table, dev);
return id;
}
static int nvidia_bl_find_device(struct driver_data **dd, unsigned pci_device, unsigned ignore_device)
{
struct pci_dev *dev = NULL;
const struct pci_device_id *id;
/* For each PCI device */
while ((dev = pci_get_device(PCI_VENDOR_ID_NVIDIA, pci_device, dev))) {
/* ... lookup id struct */
id = nvidia_bl_match_id(dev);
if (id && (!ignore_device || (dev->device != ignore_device))) {
printk(KERN_INFO "nvidia_bl: Supported Nvidia graphics"
" adapter %04x:%04x:%04x:%04x detected\n",
id->vendor, id->device,
dev->subsystem_vendor, dev->subsystem_device);
/* Setup driver data */
*dd = (struct driver_data *)id->driver_data;
(*dd)->dev = dev;
return 0;
}
}
printk(KERN_INFO "nvidia_bl: No supported Nvidia graphics adapter"
" found\n");
return -ENODEV;
}
static int nvidia_bl_map_smartdimmer(struct driver_data *dd)
{
/* Get resource properties */
const unsigned long bar_start = pci_resource_start(dd->dev, dd->bar),
bar_end = pci_resource_end(dd->dev, dd->bar),
bar_flags = pci_resource_flags(dd->dev, dd->bar);
/* Calculate register address */
const unsigned long reg_addr = bar_start + dd->reg_offset;
/* Sanity check 1: Should be a memory region containing registers */
if (!(bar_flags & IORESOURCE_MEM))
return -ENODEV;
if (bar_flags & IORESOURCE_PREFETCH)
return -ENODEV;
/* Sanity check 2: Address should not exceed the PCI BAR */
if (reg_addr + dd->reg_size - 1 > bar_end)
return -ENODEV;
/* Now really map (The address need not be page-aligned.) */
dd->smartdimmer = ioremap_nocache(reg_addr, dd->reg_size);
if (!dd->smartdimmer)
return -ENXIO;
return 0;
}
static void nvidia_bl_unmap_smartdimmer(struct driver_data *dd)
{
iounmap(dd->smartdimmer);
dd->smartdimmer = NULL;
}
/*
* Driver implementation
*/
static struct driver_data *driver_data = NULL;
static struct backlight_device *nvidia_bl_device;
#ifdef USE_PLATFORM_DRIVER
static int nvidia_bl_probe(struct platform_device *pdev)
#else
static int __init nvidia_bl_init(void)
#endif
{
struct backlight_properties props;
int err;
/* Bail-out if PCI subsystem is not initialized */
if (no_pci_devices())
return -ENODEV;
/* Check DMI whether we need to ignore some device */
dmi_check_system(nvidia_bl_ignore_table);
/* Check DMI whether we have a known system */
dmi_check_system(nvidia_bl_dmi_table);
err = nvidia_bl_find_device(&driver_data, pci_id, nvidia_bl_ignore_device);
if (err)
return err;
/* Map smartdimmer */
err = nvidia_bl_map_smartdimmer(driver_data);
if (err)
return err;
/* Register at backlight framework */
memset(&props, 0, sizeof(struct backlight_properties));
nvidia_bl_device = backlight_device_register("nvidia_backlight", NULL,
driver_data,
&driver_data->backlight_ops,
&props);
if (IS_ERR(nvidia_bl_device)) {
nvidia_bl_unmap_smartdimmer(driver_data);
return PTR_ERR(nvidia_bl_device);
}
/* Set up backlight device */
nvidia_bl_device->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
nvidia_bl_device->props.brightness =
nvidia_bl_device->ops->get_brightness(nvidia_bl_device);
backlight_update_status(nvidia_bl_device);
return 0;
}
#ifdef USE_PLATFORM_DRIVER
static int nvidia_bl_remove(struct platform_device *pdev)
#else
static void __exit nvidia_bl_exit(void)
#endif
{
/* Unregister at backlight framework */
if (nvidia_bl_device)
backlight_device_unregister(nvidia_bl_device);
/* Unmap smartdimmer */
if (driver_data->smartdimmer)
nvidia_bl_unmap_smartdimmer(driver_data);
/* Release PCI device */
if (driver_data->dev)
pci_dev_put(driver_data->dev);
#ifdef USE_PLATFORM_DRIVER
return 0;
#endif
}
/*
* Platform driver implementation
*/
#ifdef USE_PLATFORM_DRIVER
static int nvidia_bl_resume(struct platform_device *pdev)
{
backlight_update_status(nvidia_bl_device);
return 0;
}
static struct platform_driver nvidia_bl_driver = {
.probe = nvidia_bl_probe,
.remove = nvidia_bl_remove,
.resume = nvidia_bl_resume,
.driver = {
.owner = THIS_MODULE,
.name = "nvidia_bl"
},
};
static struct platform_device *nvidia_bl_platform_device;
static int __init nvidia_bl_init(void)
{
int err;
err = platform_driver_register(&nvidia_bl_driver);
if (err)
return err;
nvidia_bl_platform_device =
platform_device_register_simple("nvidia_bl", -1, NULL, 0);
if (!nvidia_bl_platform_device) {
platform_driver_unregister(&nvidia_bl_driver);
return -ENOMEM;
}
return 0;
}
static void __exit nvidia_bl_exit(void)
{
platform_device_unregister(nvidia_bl_platform_device);
platform_driver_unregister(&nvidia_bl_driver);
}
#endif /* USE_PLATFORM_DRIVER */
module_init(nvidia_bl_init);
module_exit(nvidia_bl_exit);
MODULE_AUTHOR("Mario Schwalbe <schwalbe@inf.tu-dresden.de>");
MODULE_DESCRIPTION("Nvidia-based graphics adapter backlight driver");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(dmi, nvidia_bl_dmi_table);