Want more features on Pastebin? Sign Up, it's FREE!
Guest

nvidia_bl.c

By: a guest on Nov 1st, 2010  |  syntax: C  |  size: 35.23 KB  |  views: 29  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /*
  2.  * Display backlight driver for Nvidia graphics adapters.
  3.  *
  4.  * Copyright (c) 2008-2010 Mario Schwalbe <schwalbe@inf.tu-dresden.de>
  5.  * Based on the mechanism dicovered by the author of NvClock:
  6.  *     Copyright (c) 2001-2009 Roderick Colenbrander
  7.  *     Site: http://nvclock.sourceforge.net
  8.  * Fixes and suggestions by:
  9.  *     Guillaume Zin <guillaume.zin@gmail.com>
  10.  *     Steven Barrett <damentz@gmail.com>
  11.  *
  12.  * This program is free software; you can redistribute it and/or modify
  13.  * it under the terms of the GNU General Public License as published by
  14.  * the Free Software Foundation; either version 2 of the License, or
  15.  * (at your option) any later version.
  16.  */
  17.  
  18. #include <linux/kernel.h>
  19. #include <linux/module.h>
  20. #include <linux/init.h>
  21. #include <linux/platform_device.h>
  22. #include <linux/backlight.h>
  23. #include <linux/dmi.h>
  24. #include <linux/pci.h>
  25. #include <linux/err.h>
  26. #include <linux/version.h>
  27.  
  28. /*
  29.  * Maybe the check against the subsystem vendor should be removed,
  30.  * but there's no guarantee that the chip's smartdimmer signals
  31.  * are actually connected to the display logic. Right now, these
  32.  * are the supported (read connected) vendors according to NvClock.
  33.  *
  34.  * TODO: Remove this stuff. Shouldn't be necessary.
  35.  */
  36. /* #define CONFIG_NVIDIA_BL_CHECK_SUBSYSTEM_VENDOR */
  37.  
  38. /* Check whether backlight props.state is present */
  39. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
  40.         #define HAVE_BACKLIGHT_PROPS_STATE
  41. #endif
  42.  
  43. /* Check whether we have to initialize backlight props */
  44. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34)
  45.         #define INIT_BACKLIGHT_PROPS
  46. #endif
  47.  
  48. /* Register constants */
  49. #define NV4X_BRIGHTNESS_OFFSET                          0x15f2
  50. #define NV4X_BRIGHTNESS_MASK                            0x001f
  51. #define NV5X_PDISPLAY_OFFSET                            0x00610000
  52. #define NV5X_PDISPLAY_BRIGHTNESS_OFFSET                 0x0000c084
  53. #define NV5X_PDIPSLAY_BRIGHTNESS_CONTROL_ENABLED        0x80000000
  54.  
  55. /*
  56.  * Driver private data structure
  57.  */
  58. struct driver_data {
  59.         /* PCI region (BAR) the smartdimmer register is in */
  60.         unsigned bar;
  61.         /* Register offset into this region */
  62.         unsigned long reg_offset;
  63.         /* Register size in byte */
  64.         unsigned reg_size;
  65.         /* Register mask to apply while updating the register (NV5X only) */
  66.         unsigned reg_mask;
  67.         /* Maximum brightness level in the range 0 ... max_level */
  68.         unsigned max_level;
  69.  
  70.         /* Hardware register get/set functions */
  71.         struct driver_data_ops {
  72.                 unsigned (*get_intensity)(const struct driver_data *dd);
  73.                 int (*set_intensity)(struct driver_data *dd,
  74.                                      unsigned intensity);
  75.         } ops;
  76.  
  77.         /* The device we drive */
  78.         struct pci_dev *dev;
  79.         /* Pointer to the mapped smartdimmer register */
  80.         /* volatile */ void __iomem *smartdimmer;
  81. };
  82.  
  83. /*
  84.  * Machine quirks
  85.  */
  86. struct machine_quirks {
  87.         /* Request to drive a specific device for machines
  88.          * incorporating several graphics adapters */
  89.         unsigned dev_id;
  90.         /* Some machines seem to ignore higher levels
  91.          * although supported by the graphics adapter. */
  92.         unsigned max_level;
  93. };
  94.  
  95. /*
  96.  * Module parameters
  97.  */
  98. static unsigned debug = 0;
  99. module_param_named(debug, debug, int, 0644);
  100. MODULE_PARM_DESC(debug, "Set to one to enable debugging messages.");
  101.  
  102. static unsigned shift = 0;
  103. module_param_named(shift, shift, int, 0444);
  104. MODULE_PARM_DESC(shift, "Shift the value by n bits to reduce the range.");
  105.  
  106. static unsigned dev_id = PCI_ANY_ID;
  107. module_param_named(dev_id, dev_id, int, 0444);
  108. MODULE_PARM_DESC(dev_id, "Disable auto-detection and attempt to drive exactly "
  109.         "the device of this PCI ID if present.");
  110.  
  111. static unsigned max_level = 0;
  112. module_param_named(max_level, max_level, int, 0444);
  113. MODULE_PARM_DESC(max_level, "Maximum brightness level to use in the range "
  114.         "0 ... max_level. Use with care.");
  115.  
  116. static unsigned force = 0;
  117. module_param_named(force, force, int, 0444);
  118. MODULE_PARM_DESC(force, "Force loading of the driver even if the device "
  119.         "is an unknown Nvidia graphics adapter. Use with care.");
  120.  
  121. /*
  122.  * Implementation for NV4X chips
  123.  * (NV40, NV41, NV43, NV44, NV46, NV47, NV49, NV4B, C51)
  124.  */
  125. static unsigned nv4x_get_intensity(const struct driver_data *dd)
  126. {
  127.         const unsigned value = ioread16(dd->smartdimmer);
  128.  
  129.         if (unlikely(debug))
  130.                 printk(KERN_DEBUG "nvidia_bl: register read: 0x%04x\n", value);
  131.  
  132.         return value & NV4X_BRIGHTNESS_MASK;
  133. }
  134.  
  135. static int nv4x_set_intensity(struct driver_data *dd, unsigned intensity)
  136. {
  137.         const unsigned value =
  138.                 (ioread16(dd->smartdimmer) & ~NV4X_BRIGHTNESS_MASK) |
  139.                 intensity;
  140.  
  141.         if (unlikely(debug))
  142.                 printk(KERN_DEBUG "nvidia_bl: register write: 0x%04x\n", value);
  143.  
  144.         iowrite16(value, dd->smartdimmer);
  145.         return 0;
  146. }
  147.  
  148. static const struct driver_data nv4x_driver_data __devinitconst = {
  149.         .bar        = 0,
  150.         .reg_offset = NV4X_BRIGHTNESS_OFFSET,
  151.         .reg_size   = 2,
  152.         .max_level  = 31,
  153.         .ops        = {
  154.                 .get_intensity = &nv4x_get_intensity,
  155.                 .set_intensity = &nv4x_set_intensity,
  156.         }
  157. };
  158.  
  159. /*
  160.  * Implementation for NV5X chips
  161.  * (NV50, G84, G86, G92, G94, G96, GT200)
  162.  */
  163. static unsigned nv5x_get_intensity(const struct driver_data *dd)
  164. {
  165.         unsigned value = ioread32(dd->smartdimmer);
  166.  
  167.         if (unlikely(debug))
  168.                 printk(KERN_DEBUG "nvidia_bl: register read: 0x%08x\n", value);
  169.  
  170.         value &= dd->reg_mask;
  171.         return (value <= dd->max_level) ? value : dd->max_level;
  172. }
  173.  
  174. static int nv5x_set_intensity(struct driver_data *dd, unsigned intensity)
  175. {
  176.         const unsigned value = (intensity & dd->reg_mask)
  177.                 | NV5X_PDIPSLAY_BRIGHTNESS_CONTROL_ENABLED;
  178.  
  179.         if (unlikely(debug))
  180.                 printk(KERN_DEBUG "nvidia_bl: register write: 0x%08x\n", value);
  181.  
  182.         iowrite32(value, dd->smartdimmer);
  183.         return 0;
  184. }
  185.  
  186. static const struct driver_data nv5x_driver_data __devinitconst = {
  187.         .bar        = 0,
  188.         .reg_offset = NV5X_PDISPLAY_OFFSET + NV5X_PDISPLAY_BRIGHTNESS_OFFSET,
  189.         .reg_size   = 4,
  190.         /* Could set up to 11 bits. More got ignored. */
  191.         .max_level  = 2047,
  192.         .ops        = {
  193.                 .get_intensity = &nv5x_get_intensity,
  194.                 .set_intensity = &nv5x_set_intensity,
  195.         }
  196. };
  197.  
  198. /*
  199.  * Device matching.
  200.  *
  201.  * The list of supported devices was primarily taken from Nvidia's driver
  202.  * documentation appendix A, available at:
  203.  * http://download.nvidia.com/XFree86/Linux-x86_64/<version>/README/supportedchips.html
  204.  * and completed with NvClock's device table and posts by users of Nvidia's forum at:
  205.  * http://www.nvnews.net/vbulletin/showthread.php?t=143025.
  206.  *
  207.  * Please send reports to Mario Schwalbe <schwalbe@inf.tu-dresden.de>
  208.  * and also include the output of:
  209.  * $ cat /sys/class/dmi/id/sys_vendor
  210.  * $ cat /sys/class/dmi/id/product_name
  211.  */
  212. static DEFINE_PCI_DEVICE_TABLE(nvidia_bl_device_table) = {
  213.         /* Geforce Go 7800 (195.30) */
  214.         { PCI_VDEVICE(NVIDIA, 0x0098), (kernel_ulong_t)&nv4x_driver_data },
  215.         /* Geforce Go 7800 GTX (195.30) */
  216.         { PCI_VDEVICE(NVIDIA, 0x0099), (kernel_ulong_t)&nv4x_driver_data },
  217.         /* Geforce Go 6800 (195.30) */
  218.         { PCI_VDEVICE(NVIDIA, 0x00c8), (kernel_ulong_t)&nv4x_driver_data },
  219.         /* Geforce Go 6800 Ultra (195.30) */
  220.         { PCI_VDEVICE(NVIDIA, 0x00c9), (kernel_ulong_t)&nv4x_driver_data },
  221.         /* Quadro FX Go 1400 (195.30) */
  222.         { PCI_VDEVICE(NVIDIA, 0x00cc), (kernel_ulong_t)&nv4x_driver_data },
  223.         /* Geforce Go 6600 (195.30) */
  224.         { PCI_VDEVICE(NVIDIA, 0x0144), (kernel_ulong_t)&nv4x_driver_data },
  225.         /* Geforce Go 6600 TE/6200 TE (195.30) */
  226.         { PCI_VDEVICE(NVIDIA, 0x0146), (kernel_ulong_t)&nv4x_driver_data },
  227.         /* Geforce Go 6600 (195.30) */
  228.         { PCI_VDEVICE(NVIDIA, 0x0148), (kernel_ulong_t)&nv4x_driver_data },
  229.         /* Geforce Go 6600 GT (195.30) */
  230.         { PCI_VDEVICE(NVIDIA, 0x0149), (kernel_ulong_t)&nv4x_driver_data },
  231.         /* Quadro FX 540M (195.30) */
  232.         { PCI_VDEVICE(NVIDIA, 0x014c), (kernel_ulong_t)&nv4x_driver_data },
  233.         /* Geforce Go 6200 (195.30) */
  234.         { PCI_VDEVICE(NVIDIA, 0x0164), (kernel_ulong_t)&nv4x_driver_data },
  235.         /* Geforce Go 6400 (195.30) */
  236.         { PCI_VDEVICE(NVIDIA, 0x0166), (kernel_ulong_t)&nv4x_driver_data },
  237.         /* Geforce Go 6200 (195.30) */
  238.         { PCI_VDEVICE(NVIDIA, 0x0167), (kernel_ulong_t)&nv4x_driver_data },
  239.         /* Geforce Go 6400 (195.30) */
  240.         { PCI_VDEVICE(NVIDIA, 0x0168), (kernel_ulong_t)&nv4x_driver_data },
  241.         /* Geforce Go 7200 (195.30) */
  242.         { PCI_VDEVICE(NVIDIA, 0x01d6), (kernel_ulong_t)&nv4x_driver_data },
  243.         /* Geforce Go 7300 (195.30) */
  244.         { PCI_VDEVICE(NVIDIA, 0x01d7), (kernel_ulong_t)&nv4x_driver_data },
  245.         /* Geforce Go 7400 (195.30) */
  246.         { PCI_VDEVICE(NVIDIA, 0x01d8), (kernel_ulong_t)&nv4x_driver_data },
  247.         /* Geforce Go 7400GS (NvClock) */
  248.         { PCI_VDEVICE(NVIDIA, 0x01d9), (kernel_ulong_t)&nv4x_driver_data },
  249.         /* Quadro NVS 110M (195.30) */
  250.         { PCI_VDEVICE(NVIDIA, 0x01da), (kernel_ulong_t)&nv4x_driver_data },
  251.         /* Quadro NVS 120M (195.30) */
  252.         { PCI_VDEVICE(NVIDIA, 0x01db), (kernel_ulong_t)&nv4x_driver_data },
  253.         /* Quadro FX 350M (195.30) */
  254.         { PCI_VDEVICE(NVIDIA, 0x01dc), (kernel_ulong_t)&nv4x_driver_data },
  255.         /* Geforce 7500 LE (195.30) */
  256.         { PCI_VDEVICE(NVIDIA, 0x01dd), (kernel_ulong_t)&nv4x_driver_data },
  257.         /* NV44M (NvClock) */
  258.         { PCI_VDEVICE(NVIDIA, 0x0228), (kernel_ulong_t)&nv4x_driver_data },
  259.         /* Geforce Go 6150 (195.30) */
  260.         { PCI_VDEVICE(NVIDIA, 0x0244), (kernel_ulong_t)&nv4x_driver_data },
  261.         /* Geforce Go 6100 (195.30) */
  262.         { PCI_VDEVICE(NVIDIA, 0x0247), (kernel_ulong_t)&nv4x_driver_data },
  263.         /* Geforce Go 7950 GTX (195.30) */
  264.         { PCI_VDEVICE(NVIDIA, 0x0297), (kernel_ulong_t)&nv4x_driver_data },
  265.         /* Geforce Go 7900 GS (195.30) */
  266.         { PCI_VDEVICE(NVIDIA, 0x0298), (kernel_ulong_t)&nv4x_driver_data },
  267.         /* Geforce Go 7900GTX (NvClock) / Quadro NVS 510M (195.30) */
  268.         { PCI_VDEVICE(NVIDIA, 0x0299), (kernel_ulong_t)&nv4x_driver_data },
  269.         /* Quadro FX 2500M (195.30) */
  270.         { PCI_VDEVICE(NVIDIA, 0x029a), (kernel_ulong_t)&nv4x_driver_data },
  271.         /* Quadro FX 1500M (195.30) */
  272.         { PCI_VDEVICE(NVIDIA, 0x029b), (kernel_ulong_t)&nv4x_driver_data },
  273.         /* Geforce Go 7700 (195.30) */
  274.         { PCI_VDEVICE(NVIDIA, 0x0397), (kernel_ulong_t)&nv4x_driver_data },
  275.         /* Geforce Go 7600 (195.30) */
  276.         { PCI_VDEVICE(NVIDIA, 0x0398), (kernel_ulong_t)&nv4x_driver_data },
  277.         /* Geforce Go 7600 GT (195.30) */
  278.         { PCI_VDEVICE(NVIDIA, 0x0399), (kernel_ulong_t)&nv4x_driver_data },
  279.         /* Quadro NVS 300M (NvClock) */
  280.         { PCI_VDEVICE(NVIDIA, 0x039a), (kernel_ulong_t)&nv4x_driver_data },
  281.         /* Geforce Go 7900SE (NvClock) */
  282.         { PCI_VDEVICE(NVIDIA, 0x039b), (kernel_ulong_t)&nv4x_driver_data },
  283.         /* QuadroFX 550M (NvClock) */
  284.         { PCI_VDEVICE(NVIDIA, 0x039c), (kernel_ulong_t)&nv4x_driver_data },
  285.         /* Geforce 9500M GS (195.36) */
  286.         { PCI_VDEVICE(NVIDIA, 0x0405), (kernel_ulong_t)&nv5x_driver_data },
  287.         /* Geforce NB9P-GE (NvClock) */
  288.         { PCI_VDEVICE(NVIDIA, 0x0406), (kernel_ulong_t)&nv5x_driver_data },
  289.         /* Geforce 8600M GT (195.36) */
  290.         { PCI_VDEVICE(NVIDIA, 0x0407), (kernel_ulong_t)&nv5x_driver_data },
  291.         /* Geforce 9650M GS (195.36) */
  292.         { PCI_VDEVICE(NVIDIA, 0x0408), (kernel_ulong_t)&nv5x_driver_data },
  293.         /* Geforce 8700M GT (195.36) */
  294.         { PCI_VDEVICE(NVIDIA, 0x0409), (kernel_ulong_t)&nv5x_driver_data },
  295.         /* Quadro NVS 370M (NvClock) */
  296.         { PCI_VDEVICE(NVIDIA, 0x040a), (kernel_ulong_t)&nv5x_driver_data },
  297.         /* Quadro NVS 320M (195.36) */
  298.         { PCI_VDEVICE(NVIDIA, 0x040b), (kernel_ulong_t)&nv5x_driver_data },
  299.         /* Quadro FX 570M (195.36) */
  300.         { PCI_VDEVICE(NVIDIA, 0x040c), (kernel_ulong_t)&nv5x_driver_data },
  301.         /* Quadro FX 1600M (195.36) */
  302.         { PCI_VDEVICE(NVIDIA, 0x040d), (kernel_ulong_t)&nv5x_driver_data },
  303.         /* Geforce 8600M GS (195.36) */
  304.         { PCI_VDEVICE(NVIDIA, 0x0425), (kernel_ulong_t)&nv5x_driver_data },
  305.         /* Geforce 8400M GT (195.36) */
  306.         { PCI_VDEVICE(NVIDIA, 0x0426), (kernel_ulong_t)&nv5x_driver_data },
  307.         /* Geforce 8400M GS (195.36) */
  308.         { PCI_VDEVICE(NVIDIA, 0x0427), (kernel_ulong_t)&nv5x_driver_data },
  309.         /* Geforce 8400M G (195.36) */
  310.         { PCI_VDEVICE(NVIDIA, 0x0428), (kernel_ulong_t)&nv5x_driver_data },
  311.         /* Quadro NVS 140M (195.36) */
  312.         { PCI_VDEVICE(NVIDIA, 0x0429), (kernel_ulong_t)&nv5x_driver_data },
  313.         /* Quadro NVS 130M (195.36) */
  314.         { PCI_VDEVICE(NVIDIA, 0x042a), (kernel_ulong_t)&nv5x_driver_data },
  315.         /* Quadro NVS 135M (195.36) */
  316.         { PCI_VDEVICE(NVIDIA, 0x042b), (kernel_ulong_t)&nv5x_driver_data },
  317.         /* Quadro FX 360M (195.36) */
  318.         { PCI_VDEVICE(NVIDIA, 0x042d), (kernel_ulong_t)&nv5x_driver_data },
  319.         /* Geforce 9300M G (195.36) */
  320.         { PCI_VDEVICE(NVIDIA, 0x042e), (kernel_ulong_t)&nv5x_driver_data },
  321.         /* Geforce 7150M / nForce 630M (195.36) */
  322.         { PCI_VDEVICE(NVIDIA, 0x0531), (kernel_ulong_t)&nv5x_driver_data },
  323.         /* Geforce 7000M / nForce 610M (195.36) */
  324.         { PCI_VDEVICE(NVIDIA, 0x0533), (kernel_ulong_t)&nv5x_driver_data },
  325.         /* Geforce 9800M GTX (195.36) */
  326.         { PCI_VDEVICE(NVIDIA, 0x0608), (kernel_ulong_t)&nv5x_driver_data },
  327.         /* Geforce 8800M GTS (195.36) */
  328.         { PCI_VDEVICE(NVIDIA, 0x0609), (kernel_ulong_t)&nv5x_driver_data },
  329.         /* Geforce GTX 280M (195.36) */
  330.         { PCI_VDEVICE(NVIDIA, 0x060a), (kernel_ulong_t)&nv5x_driver_data },
  331.         /* Geforce 9800M GT (195.36) */
  332.         { PCI_VDEVICE(NVIDIA, 0x060b), (kernel_ulong_t)&nv5x_driver_data },
  333.         /* Geforce 8800M GTX (195.36) */
  334.         { PCI_VDEVICE(NVIDIA, 0x060c), (kernel_ulong_t)&nv5x_driver_data },
  335.         /* Geforce GTX 285M (195.36) */
  336.         { PCI_VDEVICE(NVIDIA, 0x060f), (kernel_ulong_t)&nv5x_driver_data },
  337.         /* Geforce 9800M GTX (195.36) */
  338.         { PCI_VDEVICE(NVIDIA, 0x0617), (kernel_ulong_t)&nv5x_driver_data },
  339.         /* Geforce GTX 260M (195.36) */
  340.         { PCI_VDEVICE(NVIDIA, 0x0618), (kernel_ulong_t)&nv5x_driver_data },
  341.         /* Quadro FX 3600M (195.36) */
  342.         { PCI_VDEVICE(NVIDIA, 0x061c), (kernel_ulong_t)&nv5x_driver_data },
  343.         /* Quadro FX 2800M (195.36) */
  344.         { PCI_VDEVICE(NVIDIA, 0x061d), (kernel_ulong_t)&nv5x_driver_data },
  345.         /* Quadro FX 3700M (195.36) */
  346.         { PCI_VDEVICE(NVIDIA, 0x061e), (kernel_ulong_t)&nv5x_driver_data },
  347.         /* Quadro FX 3800M (195.36) */
  348.         { PCI_VDEVICE(NVIDIA, 0x061f), (kernel_ulong_t)&nv5x_driver_data },
  349.         /* Geforce 9800M GTS (195.36) */
  350.         { PCI_VDEVICE(NVIDIA, 0x0628), (kernel_ulong_t)&nv5x_driver_data },
  351.         /* Geforce 9700M GTS (195.36) */
  352.         { PCI_VDEVICE(NVIDIA, 0x062a), (kernel_ulong_t)&nv5x_driver_data },
  353.         /* Geforce 9800M GS (195.36) */
  354.         { PCI_VDEVICE(NVIDIA, 0x062b), (kernel_ulong_t)&nv5x_driver_data },
  355.         /* Geforce 9800M GTS (195.36) */
  356.         { PCI_VDEVICE(NVIDIA, 0x062c), (kernel_ulong_t)&nv5x_driver_data },
  357.         /* Geforce GTS 160M (195.36) */
  358.         { PCI_VDEVICE(NVIDIA, 0x0631), (kernel_ulong_t)&nv5x_driver_data },
  359.         /* Geforce GTS 150M (195.36) */
  360.         { PCI_VDEVICE(NVIDIA, 0x0632), (kernel_ulong_t)&nv5x_driver_data },
  361.         /* Quadro FX 2700M (195.36) */
  362.         { PCI_VDEVICE(NVIDIA, 0x063a), (kernel_ulong_t)&nv5x_driver_data },
  363.         /* Geforce 9600M GT (195.36) */
  364.         { PCI_VDEVICE(NVIDIA, 0x0647), (kernel_ulong_t)&nv5x_driver_data },
  365.         /* Geforce 9600M GS (195.36) */
  366.         { PCI_VDEVICE(NVIDIA, 0x0648), (kernel_ulong_t)&nv5x_driver_data },
  367.         /* Geforce 9600M GT (195.36) */
  368.         { PCI_VDEVICE(NVIDIA, 0x0649), (kernel_ulong_t)&nv5x_driver_data },
  369.         /* Geforce 9700M GT (195.36) */
  370.         { PCI_VDEVICE(NVIDIA, 0x064a), (kernel_ulong_t)&nv5x_driver_data },
  371.         /* Geforce 9500M G (195.36) */
  372.         { PCI_VDEVICE(NVIDIA, 0x064b), (kernel_ulong_t)&nv5x_driver_data },
  373.         /* Geforce 9650M GT (195.36) */
  374.         { PCI_VDEVICE(NVIDIA, 0x064c), (kernel_ulong_t)&nv5x_driver_data },
  375.         /* Geforce G 110M (195.36) */
  376.         { PCI_VDEVICE(NVIDIA, 0x0651), (kernel_ulong_t)&nv5x_driver_data },
  377.         /* Geforce GT 130M (195.36) */
  378.         { PCI_VDEVICE(NVIDIA, 0x0652), (kernel_ulong_t)&nv5x_driver_data },
  379.         /* Geforce GT 120M (195.36) */
  380.         { PCI_VDEVICE(NVIDIA, 0x0653), (kernel_ulong_t)&nv5x_driver_data },
  381.         /* Geforce GT 220M (195.36) */
  382.         { PCI_VDEVICE(NVIDIA, 0x0654), (kernel_ulong_t)&nv5x_driver_data },
  383.         /* Quadro FX 1700M (195.36) */
  384.         { PCI_VDEVICE(NVIDIA, 0x065a), (kernel_ulong_t)&nv5x_driver_data },
  385.         /* Quadro FX 770M (195.36) */
  386.         { PCI_VDEVICE(NVIDIA, 0x065c), (kernel_ulong_t)&nv5x_driver_data },
  387.         /* Geforce GTX 480M (256.53) */
  388.         { PCI_VDEVICE(NVIDIA, 0x06ca), (kernel_ulong_t)&nv5x_driver_data },
  389.         /* Geforce 9300M GS (195.36) */
  390.         { PCI_VDEVICE(NVIDIA, 0x06e5), (kernel_ulong_t)&nv5x_driver_data },
  391.         /* Geforce 9200M GS (195.36) */
  392.         { PCI_VDEVICE(NVIDIA, 0x06e8), (kernel_ulong_t)&nv5x_driver_data },
  393.         /* Geforce 9300M GS (195.36) */
  394.         { PCI_VDEVICE(NVIDIA, 0x06e9), (kernel_ulong_t)&nv5x_driver_data },
  395.         /* Quadro NVS 150M (195.36) */
  396.         { PCI_VDEVICE(NVIDIA, 0x06ea), (kernel_ulong_t)&nv5x_driver_data },
  397.         /* Quadro NVS 160M (195.36) */
  398.         { PCI_VDEVICE(NVIDIA, 0x06eb), (kernel_ulong_t)&nv5x_driver_data },
  399.         /* Geforce G 105M (195.36) */
  400.         { PCI_VDEVICE(NVIDIA, 0x06ec), (kernel_ulong_t)&nv5x_driver_data },
  401.         /* Geforce G 103M (195.36) */
  402.         { PCI_VDEVICE(NVIDIA, 0x06ef), (kernel_ulong_t)&nv5x_driver_data },
  403.         /* Geforce G 105M (195.36) */
  404.         { PCI_VDEVICE(NVIDIA, 0x06f1), (kernel_ulong_t)&nv5x_driver_data },
  405.         /* Quadro FX 370M (195.36) */
  406.         { PCI_VDEVICE(NVIDIA, 0x06fb), (kernel_ulong_t)&nv5x_driver_data },
  407.         /* Geforce 9100M G (195.36) */
  408.         { PCI_VDEVICE(NVIDIA, 0x0844), (kernel_ulong_t)&nv5x_driver_data },
  409.         /* Geforce 8200M G (195.36) */
  410.         { PCI_VDEVICE(NVIDIA, 0x0845), (kernel_ulong_t)&nv5x_driver_data },
  411.         /* Geforce 9400M G (195.36) */
  412.         { PCI_VDEVICE(NVIDIA, 0x0862), (kernel_ulong_t)&nv5x_driver_data },
  413.         /* Geforce 9400M (195.36) */
  414.         { PCI_VDEVICE(NVIDIA, 0x0863), (kernel_ulong_t)&nv5x_driver_data },
  415.         /* ION (195.36) */
  416.         { PCI_VDEVICE(NVIDIA, 0x0865), (kernel_ulong_t)&nv5x_driver_data },
  417.         /* Geforce 9400M G (195.36) */
  418.         { PCI_VDEVICE(NVIDIA, 0x0866), (kernel_ulong_t)&nv5x_driver_data },
  419.         /* Geforce 9100M G (195.36) */
  420.         { PCI_VDEVICE(NVIDIA, 0x086e), (kernel_ulong_t)&nv5x_driver_data },
  421.         /* Geforce 8200M G (195.36) */
  422.         { PCI_VDEVICE(NVIDIA, 0x086f), (kernel_ulong_t)&nv5x_driver_data },
  423.         /* Geforce 9400M (195.36) */
  424.         { PCI_VDEVICE(NVIDIA, 0x0870), (kernel_ulong_t)&nv5x_driver_data },
  425.         /* Geforce 9200 (NvClock) */
  426.         { PCI_VDEVICE(NVIDIA, 0x0871), (kernel_ulong_t)&nv5x_driver_data },
  427.         /* Geforce G 102M (195.36) */
  428.         { PCI_VDEVICE(NVIDIA, 0x0872), (kernel_ulong_t)&nv5x_driver_data },
  429.         /* Geforce G 102M (195.36) */
  430.         { PCI_VDEVICE(NVIDIA, 0x0873), (kernel_ulong_t)&nv5x_driver_data },
  431.         /* ION (195.36) */
  432.         { PCI_VDEVICE(NVIDIA, 0x0874), (kernel_ulong_t)&nv5x_driver_data },
  433.         /* ION (195.36) */
  434.         { PCI_VDEVICE(NVIDIA, 0x0876), (kernel_ulong_t)&nv5x_driver_data },
  435.         /* Quadro FX 470 (NvClock) */
  436.         { PCI_VDEVICE(NVIDIA, 0x087a), (kernel_ulong_t)&nv5x_driver_data },
  437.         /* ION (195.36) */
  438.         { PCI_VDEVICE(NVIDIA, 0x087d), (kernel_ulong_t)&nv5x_driver_data },
  439.         /* ION LE (195.36) */
  440.         { PCI_VDEVICE(NVIDIA, 0x087e), (kernel_ulong_t)&nv5x_driver_data },
  441.         /* ION LE (195.36) */
  442.         { PCI_VDEVICE(NVIDIA, 0x087f), (kernel_ulong_t)&nv5x_driver_data },
  443.         /* Geforce 320M (User report) */
  444.         { PCI_VDEVICE(NVIDIA, 0x08a0), (kernel_ulong_t)&nv5x_driver_data },
  445.         /* Geforce GT 230M (195.36) */
  446.         { PCI_VDEVICE(NVIDIA, 0x0a28), (kernel_ulong_t)&nv5x_driver_data },
  447.         /* Geforce GT 330M (195.36) */
  448.         { PCI_VDEVICE(NVIDIA, 0x0a29), (kernel_ulong_t)&nv5x_driver_data },
  449.         /* Geforce GT 230M (195.36) */
  450.         { PCI_VDEVICE(NVIDIA, 0x0a2a), (kernel_ulong_t)&nv5x_driver_data },
  451.         /* Geforce GT 330M (195.36) */
  452.         { PCI_VDEVICE(NVIDIA, 0x0a2b), (kernel_ulong_t)&nv5x_driver_data },
  453.         /* NVS 5100M (195.36) */
  454.         { PCI_VDEVICE(NVIDIA, 0x0a2c), (kernel_ulong_t)&nv5x_driver_data },
  455.         /* Geforce GT 320M (195.36) */
  456.         { PCI_VDEVICE(NVIDIA, 0x0a2d), (kernel_ulong_t)&nv5x_driver_data },
  457.         /* Geforce GT 240M (195.36) */
  458.         { PCI_VDEVICE(NVIDIA, 0x0a34), (kernel_ulong_t)&nv5x_driver_data },
  459.         /* Geforce GT 325M (195.36) */
  460.         { PCI_VDEVICE(NVIDIA, 0x0a35), (kernel_ulong_t)&nv5x_driver_data },
  461.         /* Quadro FX 880M (195.36) */
  462.         { PCI_VDEVICE(NVIDIA, 0x0a3c), (kernel_ulong_t)&nv5x_driver_data },
  463.         /* ION (195.36) */
  464.         { PCI_VDEVICE(NVIDIA, 0x0a64), (kernel_ulong_t)&nv5x_driver_data },
  465.         /* Geforce G 105M (195.36) */
  466.         { PCI_VDEVICE(NVIDIA, 0x0a68), (kernel_ulong_t)&nv5x_driver_data },
  467.         /* Geforce G 105M (195.36) */
  468.         { PCI_VDEVICE(NVIDIA, 0x0a69), (kernel_ulong_t)&nv5x_driver_data },
  469.         /* NVS 2100M (195.36) */
  470.         { PCI_VDEVICE(NVIDIA, 0x0a6a), (kernel_ulong_t)&nv5x_driver_data },
  471.         /* NVS 3100M (195.36) */
  472.         { PCI_VDEVICE(NVIDIA, 0x0a6c), (kernel_ulong_t)&nv5x_driver_data },
  473.         /* Geforce 305M (195.36) */
  474.         { PCI_VDEVICE(NVIDIA, 0x0a6e), (kernel_ulong_t)&nv5x_driver_data },
  475.         /* ION (195.36) */
  476.         { PCI_VDEVICE(NVIDIA, 0x0a6f), (kernel_ulong_t)&nv5x_driver_data },
  477.         /* Geforce 310M (195.36) */
  478.         { PCI_VDEVICE(NVIDIA, 0x0a70), (kernel_ulong_t)&nv5x_driver_data },
  479.         /* Geforce 305M (195.36) */
  480.         { PCI_VDEVICE(NVIDIA, 0x0a71), (kernel_ulong_t)&nv5x_driver_data },
  481.         /* Geforce 310M (195.36) */
  482.         { PCI_VDEVICE(NVIDIA, 0x0a72), (kernel_ulong_t)&nv5x_driver_data },
  483.         /* Geforce 305M (195.36) */
  484.         { PCI_VDEVICE(NVIDIA, 0x0a73), (kernel_ulong_t)&nv5x_driver_data },
  485.         /* Geforce G 210M (195.36) */
  486.         { PCI_VDEVICE(NVIDIA, 0x0a74), (kernel_ulong_t)&nv5x_driver_data },
  487.         /* Geforce 310M (195.36) */
  488.         { PCI_VDEVICE(NVIDIA, 0x0a75), (kernel_ulong_t)&nv5x_driver_data },
  489.         /* Quadro FX 380M (195.36) */
  490.         { PCI_VDEVICE(NVIDIA, 0x0a7c), (kernel_ulong_t)&nv5x_driver_data },
  491.         /* Geforce GTS 260M (195.36) */
  492.         { PCI_VDEVICE(NVIDIA, 0x0ca8), (kernel_ulong_t)&nv5x_driver_data },
  493.         /* Geforce GTS 250M (195.36) */
  494.         { PCI_VDEVICE(NVIDIA, 0x0ca9), (kernel_ulong_t)&nv5x_driver_data },
  495.         /* Geforce GT 335M (195.36) */
  496.         { PCI_VDEVICE(NVIDIA, 0x0caf), (kernel_ulong_t)&nv5x_driver_data },
  497.         /* Geforce GTS 350M (195.36) */
  498.         { PCI_VDEVICE(NVIDIA, 0x0cb0), (kernel_ulong_t)&nv5x_driver_data },
  499.         /* Geforce GTS 360M (195.36) */
  500.         { PCI_VDEVICE(NVIDIA, 0x0cb1), (kernel_ulong_t)&nv5x_driver_data },
  501.         /* Quadro FX 1800M (195.36) */
  502.         { PCI_VDEVICE(NVIDIA, 0x0cbc), (kernel_ulong_t)&nv5x_driver_data },
  503.  
  504.         /* end of list */
  505.         { }
  506. };
  507.  
  508. #ifdef CONFIG_NVIDIA_BL_CHECK_SUBSYSTEM_VENDOR
  509.  
  510. /*
  511.  * Supported subsystem vendors.
  512.  * Defined separately to not unnecessarily enlarge the previous array.
  513.  */
  514. static const unsigned nvidia_bl_subvendors[] __initdata = {
  515.         PCI_VENDOR_ID_APPLE,
  516.         PCI_VENDOR_ID_HP,
  517.         PCI_VENDOR_ID_SAMSUNG,
  518.         PCI_VENDOR_ID_SONY,
  519.         PCI_VENDOR_ID_TOSHIBA,
  520.         PCI_VENDOR_ID_DELL,
  521.         0x1a46, /* PCI_VENDOR_ID_ZEPTO not defined */
  522. };
  523.  
  524. #endif
  525.  
  526. /*
  527.  * Machine specific quirks used below.
  528.  */
  529. static const struct machine_quirks apple_quirks __initdata = {
  530.         .dev_id         = PCI_ANY_ID,
  531.         .max_level      = 1023
  532. };
  533.  
  534. static const struct machine_quirks apple_quirks_320m __initdata = {
  535.         .dev_id         = PCI_ANY_ID,
  536.         .max_level      = 44000
  537. };
  538.  
  539. static const struct machine_quirks sony_vpccw27fx_quirks __initdata = {
  540.         .dev_id         = PCI_ANY_ID,
  541.         .max_level      = 127000 /* might be wrong. maybe also 0x1ffff */
  542. };
  543.  
  544. static const struct machine_quirks max_level_0x1ffff __initdata = {
  545.         .dev_id         = PCI_ANY_ID,
  546.         .max_level      = 0x1ffff
  547. };
  548.  
  549. /*
  550.  * DMI matching.
  551.  */
  552. static const struct dmi_system_id *nvidia_bl_dmi_system_id;
  553.  
  554. static int nvidia_bl_dmi_match(const struct dmi_system_id *id)
  555. {
  556.         printk(KERN_INFO "nvidia_bl: %s detected\n", id->ident);
  557.         nvidia_bl_dmi_system_id = id;
  558.         return 1;
  559. }
  560.  
  561. static const struct dmi_system_id nvidia_bl_machine_table[] __initdata = {
  562.         /*
  563.          * Apple machines: Intel chipset, Nvidia graphics
  564.          */
  565.         {
  566.                 .callback       = &nvidia_bl_dmi_match,
  567.                 .ident          = "MacBookPro 3,1",
  568.                 .matches        = {
  569.                         DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
  570.                         DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"),
  571.                 },
  572.                 .driver_data    = (void *)&apple_quirks,
  573.         },
  574.         {
  575.                 .callback       = &nvidia_bl_dmi_match,
  576.                 .ident          = "MacBookPro 3,2",
  577.                 .matches        = {
  578.                         DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
  579.                         DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,2"),
  580.                 },
  581.                 .driver_data    = (void *)&apple_quirks,
  582.         },
  583.         {
  584.                 .callback       = &nvidia_bl_dmi_match,
  585.                 .ident          = "MacBookPro 4,1",
  586.                 .matches        = {
  587.                         DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
  588.                         DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro4,1"),
  589.                 },
  590.                 .driver_data    = (void *)&apple_quirks,
  591.         },
  592.  
  593.         /*
  594.          * Apple machines: Nvidia chipset, Nvidia graphics
  595.          */
  596.         {
  597.                 .callback       = &nvidia_bl_dmi_match,
  598.                 .ident          = "MacBook 5,1",
  599.                 .matches        = {
  600.                         DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
  601.                         DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5,1"),
  602.                 },
  603.                 .driver_data    = (void *)&apple_quirks,
  604.         },
  605.         {
  606.                 .callback       = &nvidia_bl_dmi_match,
  607.                 .ident          = "MacBook 5,2",
  608.                 .matches        = {
  609.                         DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
  610.                         DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5,2"),
  611.                 },
  612.                 .driver_data    = (void *)&apple_quirks,
  613.         },
  614.         {
  615.                 .callback       = &nvidia_bl_dmi_match,
  616.                 .ident          = "MacBookAir 2,1",
  617.                 .matches        = {
  618.                         DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
  619.                         DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir2,1"),
  620.                 },
  621.                 .driver_data    = (void *)&apple_quirks,
  622.         },
  623.         {
  624.                 .callback       = &nvidia_bl_dmi_match,
  625.                 .ident          = "MacBookPro 5,1",
  626.                 .matches        = {
  627.                         DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
  628.                         DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,1"),
  629.                 },
  630.                 .driver_data    = (void *)&apple_quirks,
  631.         },
  632.         {
  633.                 .callback       = &nvidia_bl_dmi_match,
  634.                 .ident          = "MacBookPro 5,2",
  635.                 .matches        = {
  636.                         DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
  637.                         DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,2"),
  638.                 },
  639.                 .driver_data    = (void *)&apple_quirks,
  640.         },
  641.         {
  642.                 .callback       = &nvidia_bl_dmi_match,
  643.                 .ident          = "MacBookPro 5,3",
  644.                 .matches        = {
  645.                         DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
  646.                         DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,3"),
  647.                 },
  648.                 .driver_data    = (void *)&apple_quirks,
  649.         },
  650.         {
  651.                 .callback       = &nvidia_bl_dmi_match,
  652.                 .ident          = "MacBookPro 5,4",
  653.                 .matches        = {
  654.                         DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
  655.                         DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,4"),
  656.                 },
  657.                 .driver_data    = (void *)&apple_quirks,
  658.         },
  659.         {
  660.                 .callback       = &nvidia_bl_dmi_match,
  661.                 .ident          = "MacBookPro 5,5",
  662.                 .matches        = {
  663.                         DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
  664.                         DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,5"),
  665.                 },
  666.                 .driver_data    = (void *)&apple_quirks,
  667.         },
  668.         {
  669.                 .callback       = &nvidia_bl_dmi_match,
  670.                 .ident          = "MacBook 6,1",
  671.                 .matches        = {
  672.                         DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
  673.                         DMI_MATCH(DMI_PRODUCT_NAME, "MacBook6,1"),
  674.                 },
  675.                 .driver_data    = (void *)&apple_quirks,
  676.         },
  677.         {
  678.                 .callback       = &nvidia_bl_dmi_match,
  679.                 .ident          = "MacBook 7,1",
  680.                 .matches        = {
  681.                         DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
  682.                         DMI_MATCH(DMI_PRODUCT_NAME, "MacBook7,1"),
  683.                 },
  684.                 .driver_data    = (void *)&apple_quirks_320m,
  685.         },
  686.         {
  687.                 .callback       = &nvidia_bl_dmi_match,
  688.                 .ident          = "MacBookPro 7,1",
  689.                 .matches        = {
  690.                         DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
  691.                         DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro7,1"),
  692.                 },
  693.                 .driver_data    = (void *)&apple_quirks_320m,
  694.         },
  695.  
  696.         /*
  697.          * Sony machines: Nvidia graphics
  698.          */
  699.         {
  700.                 .callback       = &nvidia_bl_dmi_match,
  701.                 .ident          = "Sony VGN-AW11",
  702.                 .matches        = {
  703.                         DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
  704.                         DMI_MATCH(DMI_PRODUCT_NAME, "VGN-AW11"),
  705.                 },
  706.                 .driver_data    = NULL, /* defaults */
  707.         },
  708.         {
  709.                 .callback       = &nvidia_bl_dmi_match,
  710.                 .ident          = "Sony VGN-FZ38M",
  711.                 .matches        = {
  712.                         DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
  713.                         DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ38M"),
  714.                 },
  715.                 .driver_data    = NULL, /* defaults */
  716.         },
  717.         {
  718.                 .callback       = &nvidia_bl_dmi_match,
  719.                 .ident          = "Sony VGN-FZ11E",
  720.                 .matches        = {
  721.                         DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
  722.                         DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ11E"),
  723.                 },
  724.                 .driver_data    = NULL, /* defaults */
  725.         },
  726.         {
  727.                 .callback       = &nvidia_bl_dmi_match,
  728.                 .ident          = "Sony VPCCW27FX",
  729.                 .matches        = {
  730.                         DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
  731.                         DMI_MATCH(DMI_PRODUCT_NAME, "VPCCW27FX"),
  732.                 },
  733.                 .driver_data    = (void *)&sony_vpccw27fx_quirks,
  734.         },
  735.  
  736.         /*
  737.          * Dell machines: Nvidia graphics
  738.          */
  739.         {
  740.                 .callback       = &nvidia_bl_dmi_match,
  741.                 .ident          = "Dell Inspiron 1370",
  742.                 .matches        = {
  743.                         DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
  744.                         DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1370"),
  745.                 },
  746.                 .driver_data    = NULL, /* defaults */
  747.         },
  748.         {
  749.                 .callback       = &nvidia_bl_dmi_match,
  750.                 .ident          = "Dell Vostro 3500",
  751.                 .matches        = {
  752.                         DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
  753.                         DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3500"),
  754.                 },
  755.                 .driver_data    = (void *)&max_level_0x1ffff,
  756.         },
  757.  
  758.         /*
  759.          * Toshiba machines: Nvidia graphics
  760.          */
  761.         {
  762.                 .callback       = &nvidia_bl_dmi_match,
  763.                 .ident          = "Toshiba Satellite Pro U500",
  764.                 .matches        = {
  765.                         DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
  766.                         DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE PRO U500"),
  767.                 },
  768.                 .driver_data    = (void *)&max_level_0x1ffff,
  769.         },
  770.  
  771.         /* end of list */
  772.         { }
  773. };
  774.  
  775. /*
  776.  * Driver data implementation
  777.  */
  778. static unsigned nvidia_bl_max_level_to_mask(unsigned max_level)
  779. {
  780.         int i;
  781.  
  782.         for (i = sizeof(unsigned) * 8 - 1; i >= 0; i--) {
  783.                 const unsigned bit = 1 << i;
  784.                 if (max_level & bit)
  785.                         return (bit << 1) - 1;
  786.         }
  787.  
  788.         return (unsigned)-1;
  789. }
  790.  
  791. /* missing annotation __devinitconst */
  792. static const struct pci_device_id *nvidia_bl_match_id(struct pci_dev *dev)
  793. {
  794.         /* Search id in table */
  795.         const struct pci_device_id *id =
  796.                 pci_match_id(nvidia_bl_device_table, dev);
  797.  
  798. #ifdef CONFIG_NVIDIA_BL_CHECK_SUBSYSTEM_VENDOR
  799.         int i;
  800.         if (id)
  801.                 /* ... and check subsystem vendor */
  802.                 for (i = 0; i < ARRAY_SIZE(nvidia_bl_subvendors); i++)
  803.                         if (dev->subsystem_vendor == nvidia_bl_subvendors[i])
  804.                                 return id;
  805.         return NULL;
  806. #else
  807.         return id;
  808. #endif
  809. }
  810.  
  811. /* missing annotation __devinitconst */
  812. static int nvidia_bl_find_device(struct driver_data *dd)
  813. {
  814.         const struct pci_device_id *id = NULL;
  815.         struct pci_dev *dev = NULL;
  816.  
  817.         /* For each PCI device */
  818.         while ((dev = pci_get_device(PCI_VENDOR_ID_NVIDIA, dev_id, dev))) {
  819.                 /* ... Lookup id struct */
  820.                 if ((id = nvidia_bl_match_id(dev))) {
  821.                         dev_id = id->device;
  822.  
  823.                         printk(KERN_INFO "nvidia_bl: Nvidia graphics adapter"
  824.                                " %04x:%04x (%04x:%04x) detected\n",
  825.                                id->vendor, id->device,
  826.                                dev->subsystem_vendor, dev->subsystem_device);
  827.  
  828.                         /* Setup driver data */
  829.                         *dd = *((struct driver_data *)id->driver_data);
  830.                         dd->dev = dev;
  831.                         return 0;
  832.                 }
  833.                 /* Load if forced unless not a graphics adapter */
  834.                 else if (force && (dev->class == PCI_CLASS_DISPLAY_VGA << 8)) {
  835.                         dev_id = id->device;
  836.  
  837.                         printk(KERN_INFO "nvidia_bl: Nvidia graphics adapter"
  838.                                " %04x:%04x (%04x:%04x) forced\n",
  839.                                id->vendor, id->device,
  840.                                dev->subsystem_vendor, dev->subsystem_device);
  841.  
  842.                         /* Setup driver data (assume NV5X generation) */
  843.                         *dd = nv5x_driver_data;
  844.                         dd->dev = dev;
  845.                         return 0;
  846.                 }
  847.         }
  848.  
  849.         /* Nothing found */
  850.         if (dev_id != PCI_ANY_ID)
  851.                 printk(KERN_INFO "nvidia_bl: No Nvidia graphics adapter"
  852.                        " with IDs %04x:%04x found\n",
  853.                        PCI_VENDOR_ID_NVIDIA, dev_id);
  854.         else
  855.                 printk(KERN_INFO "nvidia_bl: No supported Nvidia graphics"
  856.                        " adapter found\n");
  857.  
  858.         return -ENODEV;
  859. }
  860.  
  861. static int nvidia_bl_map_smartdimmer(struct driver_data *dd)
  862. {
  863.         /* Get resource properties */
  864.         const unsigned long bar_start = pci_resource_start(dd->dev, dd->bar),
  865.                             bar_end   = pci_resource_end(dd->dev, dd->bar),
  866.                             bar_flags = pci_resource_flags(dd->dev, dd->bar);
  867.         /* Calculate register address */
  868.         const unsigned long reg_addr  = bar_start + dd->reg_offset;
  869.  
  870.         /* Sanity check 1: Should be a memory region containing registers */
  871.         if (!(bar_flags & IORESOURCE_MEM))
  872.                 return -ENODEV;
  873.         if (bar_flags & IORESOURCE_PREFETCH)
  874.                 return -ENODEV;
  875.  
  876.         /* Sanity check 2: Address should not exceed the PCI BAR */
  877.         if (reg_addr + dd->reg_size - 1 > bar_end)
  878.                 return -ENODEV;
  879.  
  880.         if (unlikely(debug))
  881.                 printk(KERN_DEBUG "nvidia_bl: using BAR #%d at 0x%lx, "
  882.                        "smartdimmer at 0x%lx\n", dd->bar, bar_start, reg_addr);
  883.  
  884.         /* Now really map (The address need not be page-aligned.) */
  885.         dd->smartdimmer = ioremap_nocache(reg_addr, dd->reg_size);
  886.         if (!dd->smartdimmer)
  887.                 return -ENXIO;
  888.  
  889.         return 0;
  890. }
  891.  
  892. static void nvidia_bl_unmap_smartdimmer(struct driver_data *dd)
  893. {
  894.         iounmap(dd->smartdimmer);
  895. }
  896.  
  897. /*
  898.  * Backlight framework implementation.
  899.  */
  900. static int nvidia_bl_get_intensity(struct backlight_device *bd)
  901. {
  902.         const struct driver_data *dd = bl_get_data(bd);
  903.         unsigned intensity = dd->ops.get_intensity(dd);
  904.  
  905.         intensity >>= shift;
  906.  
  907.         if (unlikely(debug))
  908.                 printk(KERN_DEBUG "nvidia_bl: read brightness of %d\n",
  909.                        intensity);
  910.  
  911.         return intensity;
  912. }
  913.  
  914. static int nvidia_bl_set_intensity(struct backlight_device *bd)
  915. {
  916.         struct driver_data *dd = bl_get_data(bd);
  917.         unsigned intensity = bd->props.brightness;
  918.  
  919. #ifdef HAVE_BACKLIGHT_PROPS_STATE
  920.         if (bd->props.state & BL_CORE_FBBLANK)
  921.                 intensity = 0;
  922.         else if (bd->props.state & BL_CORE_SUSPENDED)
  923.                 intensity = 0;
  924. #endif
  925.  
  926.         if (unlikely(debug))
  927.                 printk(KERN_DEBUG "nvidia_bl: setting brightness to %d\n",
  928.                        intensity);
  929.  
  930.         intensity <<= shift;
  931.  
  932.         return dd->ops.set_intensity(dd, intensity);
  933. }
  934.  
  935. static const struct backlight_ops nvidia_bl_backlight_ops = {
  936.         .options        = BL_CORE_SUSPENDRESUME,
  937.         .get_brightness = &nvidia_bl_get_intensity,
  938.         .update_status  = &nvidia_bl_set_intensity,
  939. };
  940.  
  941. /*
  942.  * Driver implementation
  943.  */
  944. static struct driver_data driver_data;
  945. static struct backlight_device *nvidia_bl_device;
  946.  
  947. static int __init nvidia_bl_init(void)
  948. {
  949. #ifdef INIT_BACKLIGHT_PROPS
  950.         struct backlight_properties props;
  951. #endif
  952.         int err;
  953.  
  954.         /* Bail-out if PCI subsystem is not initialized */
  955.         if (no_pci_devices())
  956.                 return -ENODEV;
  957.  
  958.         /* Check DMI */
  959.         dmi_check_system(nvidia_bl_machine_table);
  960.  
  961.         /*
  962.          * Use the machine quirks from the machine table if present and not
  963.          * overridden by parameter
  964.          */
  965.         if (nvidia_bl_dmi_system_id) {
  966.                 const struct machine_quirks *quirks =
  967.                         nvidia_bl_dmi_system_id->driver_data;
  968.                 if (quirks) {
  969.                         if (dev_id == PCI_ANY_ID)
  970.                                 dev_id = quirks->dev_id;
  971.                         if (max_level == 0)
  972.                                 max_level = quirks->max_level;
  973.                 }
  974.         }
  975.  
  976.         /* Look for a supported PCI device */
  977.         err = nvidia_bl_find_device(&driver_data);
  978.         if (err)
  979.                 return err;
  980.  
  981.         /* Map smartdimmer */
  982.         err = nvidia_bl_map_smartdimmer(&driver_data);
  983.         if (err)
  984.                 return err;
  985.  
  986. #ifdef INIT_BACKLIGHT_PROPS
  987.         /* Use a dummy here. Will be initialized later. */
  988.         memset(&props, 0, sizeof(struct backlight_properties));
  989.         /* Register at backlight framework */
  990.         nvidia_bl_device = backlight_device_register("nvidia_backlight", NULL,
  991.                                                      &driver_data,
  992.                                                      &nvidia_bl_backlight_ops,
  993.                                                      &props);
  994. #else
  995.         /* Register at backlight framework */
  996.         nvidia_bl_device = backlight_device_register("nvidia_backlight", NULL,
  997.                                                      &driver_data,
  998.                                                      &nvidia_bl_backlight_ops);
  999. #endif
  1000.  
  1001.         if (IS_ERR(nvidia_bl_device)) {
  1002.                 nvidia_bl_unmap_smartdimmer(&driver_data);
  1003.                 return PTR_ERR(nvidia_bl_device);
  1004.         }
  1005.  
  1006.         /* Use the max_level parameter only if it is in reasonable range */
  1007.         if (max_level > 0)
  1008.                 driver_data.max_level = max_level;
  1009.         else
  1010.                 max_level = driver_data.max_level;
  1011.  
  1012.         /* Compute the register mask */
  1013.         driver_data.reg_mask =
  1014.                 nvidia_bl_max_level_to_mask(driver_data.max_level);
  1015.  
  1016.         /* Set up backlight device */
  1017.         nvidia_bl_device->props.brightness =
  1018.         nvidia_bl_device->props.max_brightness = driver_data.max_level >> shift;
  1019.  
  1020.         /* dump initial state if in debugging mode */
  1021.         if (unlikely(debug)) {
  1022.                 printk(KERN_DEBUG "nvidia_bl: register mask: 0x%08x\n",
  1023.                        driver_data.reg_mask);
  1024.                 nvidia_bl_device->ops->get_brightness(nvidia_bl_device);
  1025.         }
  1026.  
  1027.         /*
  1028.          * MacBook Pro 5: Hardware might report the wrong value (maximum),
  1029.          * so make sure it is right by resetting the brightness here.
  1030.          */
  1031.         backlight_update_status(nvidia_bl_device);
  1032.  
  1033.         return 0;
  1034. }
  1035.  
  1036. static void __exit nvidia_bl_exit(void)
  1037. {
  1038.         /* Unregister at backlight framework */
  1039.         if (nvidia_bl_device)
  1040.                 backlight_device_unregister(nvidia_bl_device);
  1041.  
  1042.         /* Unmap smartdimmer */
  1043.         if (driver_data.smartdimmer)
  1044.                 nvidia_bl_unmap_smartdimmer(&driver_data);
  1045.  
  1046.         /* Release PCI device */
  1047.         if (driver_data.dev)
  1048.                 pci_dev_put(driver_data.dev);
  1049. }
  1050.  
  1051. module_init(nvidia_bl_init);
  1052. module_exit(nvidia_bl_exit);
  1053.  
  1054. MODULE_AUTHOR("Mario Schwalbe <schwalbe@inf.tu-dresden.de>");
  1055. MODULE_DESCRIPTION("Nvidia-based graphics adapter display backlight driver");
  1056. MODULE_LICENSE("GPL");
  1057. MODULE_DEVICE_TABLE(dmi, nvidia_bl_machine_table);
clone this paste RAW Paste Data