pmac_backlight.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. * Miscellaneous procedures for dealing with the PowerMac hardware.
  3. * Contains support for the backlight.
  4. *
  5. * Copyright (C) 2000 Benjamin Herrenschmidt
  6. *
  7. */
  8. #include <linux/config.h>
  9. #include <linux/kernel.h>
  10. #include <linux/module.h>
  11. #include <linux/stddef.h>
  12. #include <linux/reboot.h>
  13. #include <linux/nvram.h>
  14. #include <linux/console.h>
  15. #include <asm/sections.h>
  16. #include <asm/ptrace.h>
  17. #include <asm/io.h>
  18. #include <asm/pgtable.h>
  19. #include <asm/system.h>
  20. #include <asm/prom.h>
  21. #include <asm/machdep.h>
  22. #include <asm/nvram.h>
  23. #include <asm/backlight.h>
  24. #include <linux/adb.h>
  25. #include <linux/pmu.h>
  26. static struct backlight_controller *backlighter;
  27. static void* backlighter_data;
  28. static int backlight_autosave;
  29. static int backlight_level = BACKLIGHT_MAX;
  30. static int backlight_enabled = 1;
  31. static int backlight_req_level = -1;
  32. static int backlight_req_enable = -1;
  33. static void backlight_callback(void *);
  34. static DECLARE_WORK(backlight_work, backlight_callback, NULL);
  35. void __pmac register_backlight_controller(struct backlight_controller *ctrler,
  36. void *data, char *type)
  37. {
  38. struct device_node* bk_node;
  39. char *prop;
  40. int valid = 0;
  41. /* There's already a matching controller, bail out */
  42. if (backlighter != NULL)
  43. return;
  44. bk_node = find_devices("backlight");
  45. #ifdef CONFIG_ADB_PMU
  46. /* Special case for the old PowerBook since I can't test on it */
  47. backlight_autosave = machine_is_compatible("AAPL,3400/2400")
  48. || machine_is_compatible("AAPL,3500");
  49. if ((backlight_autosave
  50. || machine_is_compatible("AAPL,PowerBook1998")
  51. || machine_is_compatible("PowerBook1,1"))
  52. && !strcmp(type, "pmu"))
  53. valid = 1;
  54. #endif
  55. if (bk_node) {
  56. prop = get_property(bk_node, "backlight-control", NULL);
  57. if (prop && !strncmp(prop, type, strlen(type)))
  58. valid = 1;
  59. }
  60. if (!valid)
  61. return;
  62. backlighter = ctrler;
  63. backlighter_data = data;
  64. if (bk_node && !backlight_autosave)
  65. prop = get_property(bk_node, "bklt", NULL);
  66. else
  67. prop = NULL;
  68. if (prop) {
  69. backlight_level = ((*prop)+1) >> 1;
  70. if (backlight_level > BACKLIGHT_MAX)
  71. backlight_level = BACKLIGHT_MAX;
  72. }
  73. #ifdef CONFIG_ADB_PMU
  74. if (backlight_autosave) {
  75. struct adb_request req;
  76. pmu_request(&req, NULL, 2, 0xd9, 0);
  77. while (!req.complete)
  78. pmu_poll();
  79. backlight_level = req.reply[0] >> 4;
  80. }
  81. #endif
  82. acquire_console_sem();
  83. if (!backlighter->set_enable(1, backlight_level, data))
  84. backlight_enabled = 1;
  85. release_console_sem();
  86. printk(KERN_INFO "Registered \"%s\" backlight controller,"
  87. "level: %d/15\n", type, backlight_level);
  88. }
  89. EXPORT_SYMBOL(register_backlight_controller);
  90. void __pmac unregister_backlight_controller(struct backlight_controller
  91. *ctrler, void *data)
  92. {
  93. /* We keep the current backlight level (for now) */
  94. if (ctrler == backlighter && data == backlighter_data)
  95. backlighter = NULL;
  96. }
  97. EXPORT_SYMBOL(unregister_backlight_controller);
  98. static int __pmac __set_backlight_enable(int enable)
  99. {
  100. int rc;
  101. if (!backlighter)
  102. return -ENODEV;
  103. acquire_console_sem();
  104. rc = backlighter->set_enable(enable, backlight_level,
  105. backlighter_data);
  106. if (!rc)
  107. backlight_enabled = enable;
  108. release_console_sem();
  109. return rc;
  110. }
  111. int __pmac set_backlight_enable(int enable)
  112. {
  113. if (!backlighter)
  114. return -ENODEV;
  115. backlight_req_enable = enable;
  116. schedule_work(&backlight_work);
  117. return 0;
  118. }
  119. EXPORT_SYMBOL(set_backlight_enable);
  120. int __pmac get_backlight_enable(void)
  121. {
  122. if (!backlighter)
  123. return -ENODEV;
  124. return backlight_enabled;
  125. }
  126. EXPORT_SYMBOL(get_backlight_enable);
  127. static int __pmac __set_backlight_level(int level)
  128. {
  129. int rc = 0;
  130. if (!backlighter)
  131. return -ENODEV;
  132. if (level < BACKLIGHT_MIN)
  133. level = BACKLIGHT_OFF;
  134. if (level > BACKLIGHT_MAX)
  135. level = BACKLIGHT_MAX;
  136. acquire_console_sem();
  137. if (backlight_enabled)
  138. rc = backlighter->set_level(level, backlighter_data);
  139. if (!rc)
  140. backlight_level = level;
  141. release_console_sem();
  142. if (!rc && !backlight_autosave) {
  143. level <<=1;
  144. if (level & 0x10)
  145. level |= 0x01;
  146. // -- todo: save to property "bklt"
  147. }
  148. return rc;
  149. }
  150. int __pmac set_backlight_level(int level)
  151. {
  152. if (!backlighter)
  153. return -ENODEV;
  154. backlight_req_level = level;
  155. schedule_work(&backlight_work);
  156. return 0;
  157. }
  158. EXPORT_SYMBOL(set_backlight_level);
  159. int __pmac get_backlight_level(void)
  160. {
  161. if (!backlighter)
  162. return -ENODEV;
  163. return backlight_level;
  164. }
  165. EXPORT_SYMBOL(get_backlight_level);
  166. static void backlight_callback(void *dummy)
  167. {
  168. int level, enable;
  169. do {
  170. level = backlight_req_level;
  171. enable = backlight_req_enable;
  172. mb();
  173. if (level >= 0)
  174. __set_backlight_level(level);
  175. if (enable >= 0)
  176. __set_backlight_enable(enable);
  177. } while(cmpxchg(&backlight_req_level, level, -1) != level ||
  178. cmpxchg(&backlight_req_enable, enable, -1) != enable);
  179. }