eeepc-laptop.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872
  1. /*
  2. * eepc-laptop.c - Asus Eee PC extras
  3. *
  4. * Based on asus_acpi.c as patched for the Eee PC by Asus:
  5. * ftp://ftp.asus.com/pub/ASUS/EeePC/701/ASUS_ACPI_071126.rar
  6. * Based on eee.c from eeepc-linux
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. */
  18. #include <linux/kernel.h>
  19. #include <linux/module.h>
  20. #include <linux/init.h>
  21. #include <linux/types.h>
  22. #include <linux/platform_device.h>
  23. #include <linux/backlight.h>
  24. #include <linux/fb.h>
  25. #include <linux/hwmon.h>
  26. #include <linux/hwmon-sysfs.h>
  27. #include <acpi/acpi_drivers.h>
  28. #include <acpi/acpi_bus.h>
  29. #include <linux/uaccess.h>
  30. #include <linux/input.h>
  31. #include <linux/rfkill.h>
  32. #define EEEPC_LAPTOP_VERSION "0.1"
  33. #define EEEPC_HOTK_NAME "Eee PC Hotkey Driver"
  34. #define EEEPC_HOTK_FILE "eeepc"
  35. #define EEEPC_HOTK_CLASS "hotkey"
  36. #define EEEPC_HOTK_DEVICE_NAME "Hotkey"
  37. #define EEEPC_HOTK_HID "ASUS010"
  38. #define EEEPC_LOG EEEPC_HOTK_FILE ": "
  39. #define EEEPC_ERR KERN_ERR EEEPC_LOG
  40. #define EEEPC_WARNING KERN_WARNING EEEPC_LOG
  41. #define EEEPC_NOTICE KERN_NOTICE EEEPC_LOG
  42. #define EEEPC_INFO KERN_INFO EEEPC_LOG
  43. /*
  44. * Definitions for Asus EeePC
  45. */
  46. #define NOTIFY_WLAN_ON 0x10
  47. #define NOTIFY_BRN_MIN 0x20
  48. #define NOTIFY_BRN_MAX 0x2f
  49. enum {
  50. DISABLE_ASL_WLAN = 0x0001,
  51. DISABLE_ASL_BLUETOOTH = 0x0002,
  52. DISABLE_ASL_IRDA = 0x0004,
  53. DISABLE_ASL_CAMERA = 0x0008,
  54. DISABLE_ASL_TV = 0x0010,
  55. DISABLE_ASL_GPS = 0x0020,
  56. DISABLE_ASL_DISPLAYSWITCH = 0x0040,
  57. DISABLE_ASL_MODEM = 0x0080,
  58. DISABLE_ASL_CARDREADER = 0x0100
  59. };
  60. enum {
  61. CM_ASL_WLAN = 0,
  62. CM_ASL_BLUETOOTH,
  63. CM_ASL_IRDA,
  64. CM_ASL_1394,
  65. CM_ASL_CAMERA,
  66. CM_ASL_TV,
  67. CM_ASL_GPS,
  68. CM_ASL_DVDROM,
  69. CM_ASL_DISPLAYSWITCH,
  70. CM_ASL_PANELBRIGHT,
  71. CM_ASL_BIOSFLASH,
  72. CM_ASL_ACPIFLASH,
  73. CM_ASL_CPUFV,
  74. CM_ASL_CPUTEMPERATURE,
  75. CM_ASL_FANCPU,
  76. CM_ASL_FANCHASSIS,
  77. CM_ASL_USBPORT1,
  78. CM_ASL_USBPORT2,
  79. CM_ASL_USBPORT3,
  80. CM_ASL_MODEM,
  81. CM_ASL_CARDREADER,
  82. CM_ASL_LID
  83. };
  84. static const char *cm_getv[] = {
  85. "WLDG", NULL, NULL, NULL,
  86. "CAMG", NULL, NULL, NULL,
  87. NULL, "PBLG", NULL, NULL,
  88. "CFVG", NULL, NULL, NULL,
  89. "USBG", NULL, NULL, "MODG",
  90. "CRDG", "LIDG"
  91. };
  92. static const char *cm_setv[] = {
  93. "WLDS", NULL, NULL, NULL,
  94. "CAMS", NULL, NULL, NULL,
  95. "SDSP", "PBLS", "HDPS", NULL,
  96. "CFVS", NULL, NULL, NULL,
  97. "USBG", NULL, NULL, "MODS",
  98. "CRDS", NULL
  99. };
  100. #define EEEPC_EC "\\_SB.PCI0.SBRG.EC0."
  101. #define EEEPC_EC_FAN_PWM EEEPC_EC "SC02" /* Fan PWM duty cycle (%) */
  102. #define EEEPC_EC_SC02 0x63
  103. #define EEEPC_EC_FAN_HRPM EEEPC_EC "SC05" /* High byte, fan speed (RPM) */
  104. #define EEEPC_EC_FAN_LRPM EEEPC_EC "SC06" /* Low byte, fan speed (RPM) */
  105. #define EEEPC_EC_FAN_CTRL EEEPC_EC "SFB3" /* Byte containing SF25 */
  106. #define EEEPC_EC_SFB3 0xD3
  107. /*
  108. * This is the main structure, we can use it to store useful information
  109. * about the hotk device
  110. */
  111. struct eeepc_hotk {
  112. struct acpi_device *device; /* the device we are in */
  113. acpi_handle handle; /* the handle of the hotk device */
  114. u32 cm_supported; /* the control methods supported
  115. by this BIOS */
  116. uint init_flag; /* Init flags */
  117. u16 event_count[128]; /* count for each event */
  118. struct input_dev *inputdev;
  119. u16 *keycode_map;
  120. struct rfkill *eeepc_wlan_rfkill;
  121. struct rfkill *eeepc_bluetooth_rfkill;
  122. };
  123. /* The actual device the driver binds to */
  124. static struct eeepc_hotk *ehotk;
  125. /* Platform device/driver */
  126. static struct platform_driver platform_driver = {
  127. .driver = {
  128. .name = EEEPC_HOTK_FILE,
  129. .owner = THIS_MODULE,
  130. }
  131. };
  132. static struct platform_device *platform_device;
  133. struct key_entry {
  134. char type;
  135. u8 code;
  136. u16 keycode;
  137. };
  138. enum { KE_KEY, KE_END };
  139. static struct key_entry eeepc_keymap[] = {
  140. /* Sleep already handled via generic ACPI code */
  141. {KE_KEY, 0x10, KEY_WLAN },
  142. {KE_KEY, 0x12, KEY_PROG1 },
  143. {KE_KEY, 0x13, KEY_MUTE },
  144. {KE_KEY, 0x14, KEY_VOLUMEDOWN },
  145. {KE_KEY, 0x15, KEY_VOLUMEUP },
  146. {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
  147. {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
  148. {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
  149. {KE_END, 0},
  150. };
  151. /*
  152. * The hotkey driver declaration
  153. */
  154. static int eeepc_hotk_add(struct acpi_device *device);
  155. static int eeepc_hotk_remove(struct acpi_device *device, int type);
  156. static const struct acpi_device_id eeepc_device_ids[] = {
  157. {EEEPC_HOTK_HID, 0},
  158. {"", 0},
  159. };
  160. MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
  161. static struct acpi_driver eeepc_hotk_driver = {
  162. .name = EEEPC_HOTK_NAME,
  163. .class = EEEPC_HOTK_CLASS,
  164. .ids = eeepc_device_ids,
  165. .ops = {
  166. .add = eeepc_hotk_add,
  167. .remove = eeepc_hotk_remove,
  168. },
  169. };
  170. /* The backlight device /sys/class/backlight */
  171. static struct backlight_device *eeepc_backlight_device;
  172. /* The hwmon device */
  173. static struct device *eeepc_hwmon_device;
  174. /*
  175. * The backlight class declaration
  176. */
  177. static int read_brightness(struct backlight_device *bd);
  178. static int update_bl_status(struct backlight_device *bd);
  179. static struct backlight_ops eeepcbl_ops = {
  180. .get_brightness = read_brightness,
  181. .update_status = update_bl_status,
  182. };
  183. MODULE_AUTHOR("Corentin Chary, Eric Cooper");
  184. MODULE_DESCRIPTION(EEEPC_HOTK_NAME);
  185. MODULE_LICENSE("GPL");
  186. /*
  187. * ACPI Helpers
  188. */
  189. static int write_acpi_int(acpi_handle handle, const char *method, int val,
  190. struct acpi_buffer *output)
  191. {
  192. struct acpi_object_list params;
  193. union acpi_object in_obj;
  194. acpi_status status;
  195. params.count = 1;
  196. params.pointer = &in_obj;
  197. in_obj.type = ACPI_TYPE_INTEGER;
  198. in_obj.integer.value = val;
  199. status = acpi_evaluate_object(handle, (char *)method, &params, output);
  200. return (status == AE_OK ? 0 : -1);
  201. }
  202. static int read_acpi_int(acpi_handle handle, const char *method, int *val)
  203. {
  204. acpi_status status;
  205. unsigned long long result;
  206. status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
  207. if (ACPI_FAILURE(status)) {
  208. *val = -1;
  209. return -1;
  210. } else {
  211. *val = result;
  212. return 0;
  213. }
  214. }
  215. static int set_acpi(int cm, int value)
  216. {
  217. if (ehotk->cm_supported & (0x1 << cm)) {
  218. const char *method = cm_setv[cm];
  219. if (method == NULL)
  220. return -ENODEV;
  221. if (write_acpi_int(ehotk->handle, method, value, NULL))
  222. printk(EEEPC_WARNING "Error writing %s\n", method);
  223. }
  224. return 0;
  225. }
  226. static int get_acpi(int cm)
  227. {
  228. int value = -1;
  229. if ((ehotk->cm_supported & (0x1 << cm))) {
  230. const char *method = cm_getv[cm];
  231. if (method == NULL)
  232. return -ENODEV;
  233. if (read_acpi_int(ehotk->handle, method, &value))
  234. printk(EEEPC_WARNING "Error reading %s\n", method);
  235. }
  236. return value;
  237. }
  238. /*
  239. * Backlight
  240. */
  241. static int read_brightness(struct backlight_device *bd)
  242. {
  243. return get_acpi(CM_ASL_PANELBRIGHT);
  244. }
  245. static int set_brightness(struct backlight_device *bd, int value)
  246. {
  247. value = max(0, min(15, value));
  248. return set_acpi(CM_ASL_PANELBRIGHT, value);
  249. }
  250. static int update_bl_status(struct backlight_device *bd)
  251. {
  252. return set_brightness(bd, bd->props.brightness);
  253. }
  254. /*
  255. * Rfkill helpers
  256. */
  257. static int eeepc_wlan_rfkill_set(void *data, enum rfkill_state state)
  258. {
  259. if (state == RFKILL_STATE_SOFT_BLOCKED)
  260. return set_acpi(CM_ASL_WLAN, 0);
  261. else
  262. return set_acpi(CM_ASL_WLAN, 1);
  263. }
  264. static int eeepc_wlan_rfkill_state(void *data, enum rfkill_state *state)
  265. {
  266. if (get_acpi(CM_ASL_WLAN) == 1)
  267. *state = RFKILL_STATE_UNBLOCKED;
  268. else
  269. *state = RFKILL_STATE_SOFT_BLOCKED;
  270. return 0;
  271. }
  272. static int eeepc_bluetooth_rfkill_set(void *data, enum rfkill_state state)
  273. {
  274. if (state == RFKILL_STATE_SOFT_BLOCKED)
  275. return set_acpi(CM_ASL_BLUETOOTH, 0);
  276. else
  277. return set_acpi(CM_ASL_BLUETOOTH, 1);
  278. }
  279. static int eeepc_bluetooth_rfkill_state(void *data, enum rfkill_state *state)
  280. {
  281. if (get_acpi(CM_ASL_BLUETOOTH) == 1)
  282. *state = RFKILL_STATE_UNBLOCKED;
  283. else
  284. *state = RFKILL_STATE_SOFT_BLOCKED;
  285. return 0;
  286. }
  287. /*
  288. * Sys helpers
  289. */
  290. static int parse_arg(const char *buf, unsigned long count, int *val)
  291. {
  292. if (!count)
  293. return 0;
  294. if (sscanf(buf, "%i", val) != 1)
  295. return -EINVAL;
  296. return count;
  297. }
  298. static ssize_t store_sys_acpi(int cm, const char *buf, size_t count)
  299. {
  300. int rv, value;
  301. rv = parse_arg(buf, count, &value);
  302. if (rv > 0)
  303. set_acpi(cm, value);
  304. return rv;
  305. }
  306. static ssize_t show_sys_acpi(int cm, char *buf)
  307. {
  308. return sprintf(buf, "%d\n", get_acpi(cm));
  309. }
  310. #define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \
  311. static ssize_t show_##_name(struct device *dev, \
  312. struct device_attribute *attr, \
  313. char *buf) \
  314. { \
  315. return show_sys_acpi(_cm, buf); \
  316. } \
  317. static ssize_t store_##_name(struct device *dev, \
  318. struct device_attribute *attr, \
  319. const char *buf, size_t count) \
  320. { \
  321. return store_sys_acpi(_cm, buf, count); \
  322. } \
  323. static struct device_attribute dev_attr_##_name = { \
  324. .attr = { \
  325. .name = __stringify(_name), \
  326. .mode = 0644 }, \
  327. .show = show_##_name, \
  328. .store = store_##_name, \
  329. }
  330. EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA);
  331. EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER);
  332. EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH);
  333. static struct attribute *platform_attributes[] = {
  334. &dev_attr_camera.attr,
  335. &dev_attr_cardr.attr,
  336. &dev_attr_disp.attr,
  337. NULL
  338. };
  339. static struct attribute_group platform_attribute_group = {
  340. .attrs = platform_attributes
  341. };
  342. /*
  343. * Hotkey functions
  344. */
  345. static struct key_entry *eepc_get_entry_by_scancode(int code)
  346. {
  347. struct key_entry *key;
  348. for (key = eeepc_keymap; key->type != KE_END; key++)
  349. if (code == key->code)
  350. return key;
  351. return NULL;
  352. }
  353. static struct key_entry *eepc_get_entry_by_keycode(int code)
  354. {
  355. struct key_entry *key;
  356. for (key = eeepc_keymap; key->type != KE_END; key++)
  357. if (code == key->keycode && key->type == KE_KEY)
  358. return key;
  359. return NULL;
  360. }
  361. static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
  362. {
  363. struct key_entry *key = eepc_get_entry_by_scancode(scancode);
  364. if (key && key->type == KE_KEY) {
  365. *keycode = key->keycode;
  366. return 0;
  367. }
  368. return -EINVAL;
  369. }
  370. static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode)
  371. {
  372. struct key_entry *key;
  373. int old_keycode;
  374. if (keycode < 0 || keycode > KEY_MAX)
  375. return -EINVAL;
  376. key = eepc_get_entry_by_scancode(scancode);
  377. if (key && key->type == KE_KEY) {
  378. old_keycode = key->keycode;
  379. key->keycode = keycode;
  380. set_bit(keycode, dev->keybit);
  381. if (!eepc_get_entry_by_keycode(old_keycode))
  382. clear_bit(old_keycode, dev->keybit);
  383. return 0;
  384. }
  385. return -EINVAL;
  386. }
  387. static int eeepc_hotk_check(void)
  388. {
  389. const struct key_entry *key;
  390. struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  391. int result;
  392. result = acpi_bus_get_status(ehotk->device);
  393. if (result)
  394. return result;
  395. if (ehotk->device->status.present) {
  396. if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag,
  397. &buffer)) {
  398. printk(EEEPC_ERR "Hotkey initialization failed\n");
  399. return -ENODEV;
  400. } else {
  401. printk(EEEPC_NOTICE "Hotkey init flags 0x%x\n",
  402. ehotk->init_flag);
  403. }
  404. /* get control methods supported */
  405. if (read_acpi_int(ehotk->handle, "CMSG"
  406. , &ehotk->cm_supported)) {
  407. printk(EEEPC_ERR
  408. "Get control methods supported failed\n");
  409. return -ENODEV;
  410. } else {
  411. printk(EEEPC_INFO
  412. "Get control methods supported: 0x%x\n",
  413. ehotk->cm_supported);
  414. }
  415. ehotk->inputdev = input_allocate_device();
  416. if (!ehotk->inputdev) {
  417. printk(EEEPC_INFO "Unable to allocate input device\n");
  418. return 0;
  419. }
  420. ehotk->inputdev->name = "Asus EeePC extra buttons";
  421. ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0";
  422. ehotk->inputdev->id.bustype = BUS_HOST;
  423. ehotk->inputdev->getkeycode = eeepc_getkeycode;
  424. ehotk->inputdev->setkeycode = eeepc_setkeycode;
  425. for (key = eeepc_keymap; key->type != KE_END; key++) {
  426. switch (key->type) {
  427. case KE_KEY:
  428. set_bit(EV_KEY, ehotk->inputdev->evbit);
  429. set_bit(key->keycode, ehotk->inputdev->keybit);
  430. break;
  431. }
  432. }
  433. result = input_register_device(ehotk->inputdev);
  434. if (result) {
  435. printk(EEEPC_INFO "Unable to register input device\n");
  436. input_free_device(ehotk->inputdev);
  437. return 0;
  438. }
  439. } else {
  440. printk(EEEPC_ERR "Hotkey device not present, aborting\n");
  441. return -EINVAL;
  442. }
  443. return 0;
  444. }
  445. static void notify_brn(void)
  446. {
  447. struct backlight_device *bd = eeepc_backlight_device;
  448. bd->props.brightness = read_brightness(bd);
  449. }
  450. static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
  451. {
  452. static struct key_entry *key;
  453. if (!ehotk)
  454. return;
  455. if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
  456. notify_brn();
  457. acpi_bus_generate_proc_event(ehotk->device, event,
  458. ehotk->event_count[event % 128]++);
  459. if (ehotk->inputdev) {
  460. key = eepc_get_entry_by_scancode(event);
  461. if (key) {
  462. switch (key->type) {
  463. case KE_KEY:
  464. input_report_key(ehotk->inputdev, key->keycode,
  465. 1);
  466. input_sync(ehotk->inputdev);
  467. input_report_key(ehotk->inputdev, key->keycode,
  468. 0);
  469. input_sync(ehotk->inputdev);
  470. break;
  471. }
  472. }
  473. }
  474. }
  475. static int eeepc_hotk_add(struct acpi_device *device)
  476. {
  477. acpi_status status = AE_OK;
  478. int result;
  479. if (!device)
  480. return -EINVAL;
  481. printk(EEEPC_NOTICE EEEPC_HOTK_NAME "\n");
  482. ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL);
  483. if (!ehotk)
  484. return -ENOMEM;
  485. ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
  486. ehotk->handle = device->handle;
  487. strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME);
  488. strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS);
  489. device->driver_data = ehotk;
  490. ehotk->device = device;
  491. result = eeepc_hotk_check();
  492. if (result)
  493. goto end;
  494. status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY,
  495. eeepc_hotk_notify, ehotk);
  496. if (ACPI_FAILURE(status))
  497. printk(EEEPC_ERR "Error installing notify handler\n");
  498. if (get_acpi(CM_ASL_WLAN) != -1) {
  499. ehotk->eeepc_wlan_rfkill = rfkill_allocate(&device->dev,
  500. RFKILL_TYPE_WLAN);
  501. if (!ehotk->eeepc_wlan_rfkill)
  502. goto end;
  503. ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan";
  504. ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set;
  505. ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state;
  506. if (get_acpi(CM_ASL_WLAN) == 1)
  507. ehotk->eeepc_wlan_rfkill->state =
  508. RFKILL_STATE_UNBLOCKED;
  509. else
  510. ehotk->eeepc_wlan_rfkill->state =
  511. RFKILL_STATE_SOFT_BLOCKED;
  512. rfkill_register(ehotk->eeepc_wlan_rfkill);
  513. }
  514. if (get_acpi(CM_ASL_BLUETOOTH) != -1) {
  515. ehotk->eeepc_bluetooth_rfkill =
  516. rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH);
  517. if (!ehotk->eeepc_bluetooth_rfkill)
  518. goto end;
  519. ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth";
  520. ehotk->eeepc_bluetooth_rfkill->toggle_radio =
  521. eeepc_bluetooth_rfkill_set;
  522. ehotk->eeepc_bluetooth_rfkill->get_state =
  523. eeepc_bluetooth_rfkill_state;
  524. if (get_acpi(CM_ASL_BLUETOOTH) == 1)
  525. ehotk->eeepc_bluetooth_rfkill->state =
  526. RFKILL_STATE_UNBLOCKED;
  527. else
  528. ehotk->eeepc_bluetooth_rfkill->state =
  529. RFKILL_STATE_SOFT_BLOCKED;
  530. rfkill_register(ehotk->eeepc_bluetooth_rfkill);
  531. }
  532. end:
  533. if (result) {
  534. kfree(ehotk);
  535. ehotk = NULL;
  536. }
  537. return result;
  538. }
  539. static int eeepc_hotk_remove(struct acpi_device *device, int type)
  540. {
  541. acpi_status status = 0;
  542. if (!device || !acpi_driver_data(device))
  543. return -EINVAL;
  544. status = acpi_remove_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY,
  545. eeepc_hotk_notify);
  546. if (ACPI_FAILURE(status))
  547. printk(EEEPC_ERR "Error removing notify handler\n");
  548. kfree(ehotk);
  549. return 0;
  550. }
  551. /*
  552. * Hwmon
  553. */
  554. static int eeepc_get_fan_pwm(void)
  555. {
  556. int value = 0;
  557. read_acpi_int(NULL, EEEPC_EC_FAN_PWM, &value);
  558. value = value * 255 / 100;
  559. return (value);
  560. }
  561. static void eeepc_set_fan_pwm(int value)
  562. {
  563. value = SENSORS_LIMIT(value, 0, 255);
  564. value = value * 100 / 255;
  565. ec_write(EEEPC_EC_SC02, value);
  566. }
  567. static int eeepc_get_fan_rpm(void)
  568. {
  569. int high = 0;
  570. int low = 0;
  571. read_acpi_int(NULL, EEEPC_EC_FAN_HRPM, &high);
  572. read_acpi_int(NULL, EEEPC_EC_FAN_LRPM, &low);
  573. return (high << 8 | low);
  574. }
  575. static int eeepc_get_fan_ctrl(void)
  576. {
  577. int value = 0;
  578. read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value);
  579. return ((value & 0x02 ? 1 : 0));
  580. }
  581. static void eeepc_set_fan_ctrl(int manual)
  582. {
  583. int value = 0;
  584. read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value);
  585. if (manual)
  586. value |= 0x02;
  587. else
  588. value &= ~0x02;
  589. ec_write(EEEPC_EC_SFB3, value);
  590. }
  591. static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count)
  592. {
  593. int rv, value;
  594. rv = parse_arg(buf, count, &value);
  595. if (rv > 0)
  596. set(value);
  597. return rv;
  598. }
  599. static ssize_t show_sys_hwmon(int (*get)(void), char *buf)
  600. {
  601. return sprintf(buf, "%d\n", get());
  602. }
  603. #define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _set, _get) \
  604. static ssize_t show_##_name(struct device *dev, \
  605. struct device_attribute *attr, \
  606. char *buf) \
  607. { \
  608. return show_sys_hwmon(_set, buf); \
  609. } \
  610. static ssize_t store_##_name(struct device *dev, \
  611. struct device_attribute *attr, \
  612. const char *buf, size_t count) \
  613. { \
  614. return store_sys_hwmon(_get, buf, count); \
  615. } \
  616. static SENSOR_DEVICE_ATTR(_name, _mode, show_##_name, store_##_name, 0);
  617. EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL);
  618. EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR,
  619. eeepc_get_fan_pwm, eeepc_set_fan_pwm);
  620. EEEPC_CREATE_SENSOR_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
  621. eeepc_get_fan_ctrl, eeepc_set_fan_ctrl);
  622. static ssize_t
  623. show_name(struct device *dev, struct device_attribute *attr, char *buf)
  624. {
  625. return sprintf(buf, "eeepc\n");
  626. }
  627. static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
  628. static struct attribute *hwmon_attributes[] = {
  629. &sensor_dev_attr_pwm1.dev_attr.attr,
  630. &sensor_dev_attr_fan1_input.dev_attr.attr,
  631. &sensor_dev_attr_pwm1_enable.dev_attr.attr,
  632. &sensor_dev_attr_name.dev_attr.attr,
  633. NULL
  634. };
  635. static struct attribute_group hwmon_attribute_group = {
  636. .attrs = hwmon_attributes
  637. };
  638. /*
  639. * exit/init
  640. */
  641. static void eeepc_backlight_exit(void)
  642. {
  643. if (eeepc_backlight_device)
  644. backlight_device_unregister(eeepc_backlight_device);
  645. if (ehotk->inputdev)
  646. input_unregister_device(ehotk->inputdev);
  647. if (ehotk->eeepc_wlan_rfkill)
  648. rfkill_unregister(ehotk->eeepc_wlan_rfkill);
  649. if (ehotk->eeepc_bluetooth_rfkill)
  650. rfkill_unregister(ehotk->eeepc_bluetooth_rfkill);
  651. eeepc_backlight_device = NULL;
  652. }
  653. static void eeepc_hwmon_exit(void)
  654. {
  655. struct device *hwmon;
  656. hwmon = eeepc_hwmon_device;
  657. if (!hwmon)
  658. return ;
  659. sysfs_remove_group(&hwmon->kobj,
  660. &hwmon_attribute_group);
  661. hwmon_device_unregister(hwmon);
  662. eeepc_hwmon_device = NULL;
  663. }
  664. static void __exit eeepc_laptop_exit(void)
  665. {
  666. eeepc_backlight_exit();
  667. eeepc_hwmon_exit();
  668. acpi_bus_unregister_driver(&eeepc_hotk_driver);
  669. sysfs_remove_group(&platform_device->dev.kobj,
  670. &platform_attribute_group);
  671. platform_device_unregister(platform_device);
  672. platform_driver_unregister(&platform_driver);
  673. }
  674. static int eeepc_backlight_init(struct device *dev)
  675. {
  676. struct backlight_device *bd;
  677. bd = backlight_device_register(EEEPC_HOTK_FILE, dev,
  678. NULL, &eeepcbl_ops);
  679. if (IS_ERR(bd)) {
  680. printk(EEEPC_ERR
  681. "Could not register eeepc backlight device\n");
  682. eeepc_backlight_device = NULL;
  683. return PTR_ERR(bd);
  684. }
  685. eeepc_backlight_device = bd;
  686. bd->props.max_brightness = 15;
  687. bd->props.brightness = read_brightness(NULL);
  688. bd->props.power = FB_BLANK_UNBLANK;
  689. backlight_update_status(bd);
  690. return 0;
  691. }
  692. static int eeepc_hwmon_init(struct device *dev)
  693. {
  694. struct device *hwmon;
  695. int result;
  696. hwmon = hwmon_device_register(dev);
  697. if (IS_ERR(hwmon)) {
  698. printk(EEEPC_ERR
  699. "Could not register eeepc hwmon device\n");
  700. eeepc_hwmon_device = NULL;
  701. return PTR_ERR(hwmon);
  702. }
  703. eeepc_hwmon_device = hwmon;
  704. result = sysfs_create_group(&hwmon->kobj,
  705. &hwmon_attribute_group);
  706. if (result)
  707. eeepc_hwmon_exit();
  708. return result;
  709. }
  710. static int __init eeepc_laptop_init(void)
  711. {
  712. struct device *dev;
  713. int result;
  714. if (acpi_disabled)
  715. return -ENODEV;
  716. result = acpi_bus_register_driver(&eeepc_hotk_driver);
  717. if (result < 0)
  718. return result;
  719. if (!ehotk) {
  720. acpi_bus_unregister_driver(&eeepc_hotk_driver);
  721. return -ENODEV;
  722. }
  723. dev = acpi_get_physical_device(ehotk->device->handle);
  724. if (!acpi_video_backlight_support()) {
  725. result = eeepc_backlight_init(dev);
  726. if (result)
  727. goto fail_backlight;
  728. } else
  729. printk(EEEPC_INFO "Backlight controlled by ACPI video "
  730. "driver\n");
  731. result = eeepc_hwmon_init(dev);
  732. if (result)
  733. goto fail_hwmon;
  734. /* Register platform stuff */
  735. result = platform_driver_register(&platform_driver);
  736. if (result)
  737. goto fail_platform_driver;
  738. platform_device = platform_device_alloc(EEEPC_HOTK_FILE, -1);
  739. if (!platform_device) {
  740. result = -ENOMEM;
  741. goto fail_platform_device1;
  742. }
  743. result = platform_device_add(platform_device);
  744. if (result)
  745. goto fail_platform_device2;
  746. result = sysfs_create_group(&platform_device->dev.kobj,
  747. &platform_attribute_group);
  748. if (result)
  749. goto fail_sysfs;
  750. return 0;
  751. fail_sysfs:
  752. platform_device_del(platform_device);
  753. fail_platform_device2:
  754. platform_device_put(platform_device);
  755. fail_platform_device1:
  756. platform_driver_unregister(&platform_driver);
  757. fail_platform_driver:
  758. eeepc_hwmon_exit();
  759. fail_hwmon:
  760. eeepc_backlight_exit();
  761. fail_backlight:
  762. return result;
  763. }
  764. module_init(eeepc_laptop_init);
  765. module_exit(eeepc_laptop_exit);