Advertisement
Guest User

nvidia_bl.c

a guest
Nov 1st, 2010
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 35.23 KB | None | 0 0
  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);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement