mbp_nvidia_bl.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /*
  2. * Backlight Driver for Nvidia 8600 in Macbook Pro
  3. *
  4. * Copyright (c) Red Hat <mjg@redhat.com>
  5. * Based on code from Pommed:
  6. * Copyright (C) 2006 Nicolas Boichat <nicolas @boichat.ch>
  7. * Copyright (C) 2006 Felipe Alfaro Solana <felipe_alfaro @linuxmail.org>
  8. * Copyright (C) 2007 Julien BLACHE <jb@jblache.org>
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2 as
  12. * published by the Free Software Foundation.
  13. *
  14. * This driver triggers SMIs which cause the firmware to change the
  15. * backlight brightness. This is icky in many ways, but it's impractical to
  16. * get at the firmware code in order to figure out what it's actually doing.
  17. */
  18. #include <linux/module.h>
  19. #include <linux/kernel.h>
  20. #include <linux/init.h>
  21. #include <linux/platform_device.h>
  22. #include <linux/backlight.h>
  23. #include <linux/err.h>
  24. #include <linux/dmi.h>
  25. #include <linux/io.h>
  26. static struct backlight_device *mbp_backlight_device;
  27. /* Structure to be passed to the DMI_MATCH function. */
  28. struct dmi_match_data {
  29. /* I/O resource to allocate. */
  30. unsigned long iostart;
  31. unsigned long iolen;
  32. /* Backlight operations structure. */
  33. struct backlight_ops backlight_ops;
  34. };
  35. /*
  36. * Implementation for MacBooks with Intel chipset.
  37. */
  38. static int intel_chipset_send_intensity(struct backlight_device *bd)
  39. {
  40. int intensity = bd->props.brightness;
  41. outb(0x04 | (intensity << 4), 0xb3);
  42. outb(0xbf, 0xb2);
  43. return 0;
  44. }
  45. static int intel_chipset_get_intensity(struct backlight_device *bd)
  46. {
  47. outb(0x03, 0xb3);
  48. outb(0xbf, 0xb2);
  49. return inb(0xb3) >> 4;
  50. }
  51. static const struct dmi_match_data intel_chipset_data = {
  52. .iostart = 0xb2,
  53. .iolen = 2,
  54. .backlight_ops = {
  55. .options = BL_CORE_SUSPENDRESUME,
  56. .get_brightness = intel_chipset_get_intensity,
  57. .update_status = intel_chipset_send_intensity,
  58. }
  59. };
  60. /*
  61. * Implementation for MacBooks with Nvidia chipset.
  62. */
  63. static int nvidia_chipset_send_intensity(struct backlight_device *bd)
  64. {
  65. int intensity = bd->props.brightness;
  66. outb(0x04 | (intensity << 4), 0x52f);
  67. outb(0xbf, 0x52e);
  68. return 0;
  69. }
  70. static int nvidia_chipset_get_intensity(struct backlight_device *bd)
  71. {
  72. outb(0x03, 0x52f);
  73. outb(0xbf, 0x52e);
  74. return inb(0x52f) >> 4;
  75. }
  76. static const struct dmi_match_data nvidia_chipset_data = {
  77. .iostart = 0x52e,
  78. .iolen = 2,
  79. .backlight_ops = {
  80. .options = BL_CORE_SUSPENDRESUME,
  81. .get_brightness = nvidia_chipset_get_intensity,
  82. .update_status = nvidia_chipset_send_intensity
  83. }
  84. };
  85. /*
  86. * DMI matching.
  87. */
  88. static /* const */ struct dmi_match_data *driver_data;
  89. static int mbp_dmi_match(const struct dmi_system_id *id)
  90. {
  91. driver_data = id->driver_data;
  92. printk(KERN_INFO "mbp_nvidia_bl: %s detected\n", id->ident);
  93. return 1;
  94. }
  95. static const struct dmi_system_id __initdata mbp_device_table[] = {
  96. {
  97. .callback = mbp_dmi_match,
  98. .ident = "MacBookPro 3,1",
  99. .matches = {
  100. DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
  101. DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"),
  102. },
  103. .driver_data = (void *)&intel_chipset_data,
  104. },
  105. {
  106. .callback = mbp_dmi_match,
  107. .ident = "MacBookPro 3,2",
  108. .matches = {
  109. DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
  110. DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,2"),
  111. },
  112. .driver_data = (void *)&intel_chipset_data,
  113. },
  114. {
  115. .callback = mbp_dmi_match,
  116. .ident = "MacBookPro 4,1",
  117. .matches = {
  118. DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
  119. DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro4,1"),
  120. },
  121. .driver_data = (void *)&intel_chipset_data,
  122. },
  123. {
  124. .callback = mbp_dmi_match,
  125. .ident = "MacBook 5,1",
  126. .matches = {
  127. DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
  128. DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5,1"),
  129. },
  130. .driver_data = (void *)&nvidia_chipset_data,
  131. },
  132. {
  133. .callback = mbp_dmi_match,
  134. .ident = "MacBookAir 2,1",
  135. .matches = {
  136. DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
  137. DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir2,1"),
  138. },
  139. .driver_data = (void *)&nvidia_chipset_data,
  140. },
  141. {
  142. .callback = mbp_dmi_match,
  143. .ident = "MacBookPro 5,1",
  144. .matches = {
  145. DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
  146. DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,1"),
  147. },
  148. .driver_data = (void *)&nvidia_chipset_data,
  149. },
  150. { }
  151. };
  152. static int __init mbp_init(void)
  153. {
  154. if (!dmi_check_system(mbp_device_table))
  155. return -ENODEV;
  156. if (!request_region(driver_data->iostart, driver_data->iolen,
  157. "Macbook Pro backlight"))
  158. return -ENXIO;
  159. mbp_backlight_device = backlight_device_register("mbp_backlight",
  160. NULL, NULL, &driver_data->backlight_ops);
  161. if (IS_ERR(mbp_backlight_device)) {
  162. release_region(driver_data->iostart, driver_data->iolen);
  163. return PTR_ERR(mbp_backlight_device);
  164. }
  165. mbp_backlight_device->props.max_brightness = 15;
  166. mbp_backlight_device->props.brightness =
  167. driver_data->backlight_ops.get_brightness(mbp_backlight_device);
  168. backlight_update_status(mbp_backlight_device);
  169. return 0;
  170. }
  171. static void __exit mbp_exit(void)
  172. {
  173. backlight_device_unregister(mbp_backlight_device);
  174. release_region(driver_data->iostart, driver_data->iolen);
  175. }
  176. module_init(mbp_init);
  177. module_exit(mbp_exit);
  178. MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
  179. MODULE_DESCRIPTION("Nvidia-based Macbook Pro Backlight Driver");
  180. MODULE_LICENSE("GPL");
  181. MODULE_DEVICE_TABLE(dmi, mbp_device_table);