toshiba_acpi.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068
  1. /*
  2. * toshiba_acpi.c - Toshiba Laptop ACPI Extras
  3. *
  4. *
  5. * Copyright (C) 2002-2004 John Belmonte
  6. * Copyright (C) 2008 Philip Langdale
  7. * Copyright (C) 2010 Pierre Ducroquet
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  22. *
  23. *
  24. * The devolpment page for this driver is located at
  25. * http://memebeam.org/toys/ToshibaAcpiDriver.
  26. *
  27. * Credits:
  28. * Jonathan A. Buzzard - Toshiba HCI info, and critical tips on reverse
  29. * engineering the Windows drivers
  30. * Yasushi Nagato - changes for linux kernel 2.4 -> 2.5
  31. * Rob Miller - TV out and hotkeys help
  32. *
  33. *
  34. * TODO
  35. *
  36. */
  37. #define TOSHIBA_ACPI_VERSION "0.19"
  38. #define PROC_INTERFACE_VERSION 1
  39. #include <linux/kernel.h>
  40. #include <linux/module.h>
  41. #include <linux/init.h>
  42. #include <linux/types.h>
  43. #include <linux/proc_fs.h>
  44. #include <linux/seq_file.h>
  45. #include <linux/backlight.h>
  46. #include <linux/platform_device.h>
  47. #include <linux/rfkill.h>
  48. #include <linux/input.h>
  49. #include <linux/input/sparse-keymap.h>
  50. #include <linux/leds.h>
  51. #include <linux/slab.h>
  52. #include <asm/uaccess.h>
  53. #include <acpi/acpi_drivers.h>
  54. MODULE_AUTHOR("John Belmonte");
  55. MODULE_DESCRIPTION("Toshiba Laptop ACPI Extras Driver");
  56. MODULE_LICENSE("GPL");
  57. #define MY_LOGPREFIX "toshiba_acpi: "
  58. #define MY_ERR KERN_ERR MY_LOGPREFIX
  59. #define MY_NOTICE KERN_NOTICE MY_LOGPREFIX
  60. #define MY_INFO KERN_INFO MY_LOGPREFIX
  61. /* Toshiba ACPI method paths */
  62. #define METHOD_LCD_BRIGHTNESS "\\_SB_.PCI0.VGA_.LCD_._BCM"
  63. #define TOSH_INTERFACE_1 "\\_SB_.VALD"
  64. #define TOSH_INTERFACE_2 "\\_SB_.VALZ"
  65. #define METHOD_VIDEO_OUT "\\_SB_.VALX.DSSX"
  66. #define GHCI_METHOD ".GHCI"
  67. /* Toshiba HCI interface definitions
  68. *
  69. * HCI is Toshiba's "Hardware Control Interface" which is supposed to
  70. * be uniform across all their models. Ideally we would just call
  71. * dedicated ACPI methods instead of using this primitive interface.
  72. * However the ACPI methods seem to be incomplete in some areas (for
  73. * example they allow setting, but not reading, the LCD brightness value),
  74. * so this is still useful.
  75. */
  76. #define HCI_WORDS 6
  77. /* operations */
  78. #define HCI_SET 0xff00
  79. #define HCI_GET 0xfe00
  80. /* return codes */
  81. #define HCI_SUCCESS 0x0000
  82. #define HCI_FAILURE 0x1000
  83. #define HCI_NOT_SUPPORTED 0x8000
  84. #define HCI_EMPTY 0x8c00
  85. /* registers */
  86. #define HCI_FAN 0x0004
  87. #define HCI_SYSTEM_EVENT 0x0016
  88. #define HCI_VIDEO_OUT 0x001c
  89. #define HCI_HOTKEY_EVENT 0x001e
  90. #define HCI_LCD_BRIGHTNESS 0x002a
  91. #define HCI_WIRELESS 0x0056
  92. /* field definitions */
  93. #define HCI_LCD_BRIGHTNESS_BITS 3
  94. #define HCI_LCD_BRIGHTNESS_SHIFT (16-HCI_LCD_BRIGHTNESS_BITS)
  95. #define HCI_LCD_BRIGHTNESS_LEVELS (1 << HCI_LCD_BRIGHTNESS_BITS)
  96. #define HCI_VIDEO_OUT_LCD 0x1
  97. #define HCI_VIDEO_OUT_CRT 0x2
  98. #define HCI_VIDEO_OUT_TV 0x4
  99. #define HCI_WIRELESS_KILL_SWITCH 0x01
  100. #define HCI_WIRELESS_BT_PRESENT 0x0f
  101. #define HCI_WIRELESS_BT_ATTACH 0x40
  102. #define HCI_WIRELESS_BT_POWER 0x80
  103. static const struct acpi_device_id toshiba_device_ids[] = {
  104. {"TOS6200", 0},
  105. {"TOS6208", 0},
  106. {"TOS1900", 0},
  107. {"", 0},
  108. };
  109. MODULE_DEVICE_TABLE(acpi, toshiba_device_ids);
  110. static const struct key_entry toshiba_acpi_keymap[] __initconst = {
  111. { KE_KEY, 0x101, { KEY_MUTE } },
  112. { KE_KEY, 0x102, { KEY_ZOOMOUT } },
  113. { KE_KEY, 0x103, { KEY_ZOOMIN } },
  114. { KE_KEY, 0x13b, { KEY_COFFEE } },
  115. { KE_KEY, 0x13c, { KEY_BATTERY } },
  116. { KE_KEY, 0x13d, { KEY_SLEEP } },
  117. { KE_KEY, 0x13e, { KEY_SUSPEND } },
  118. { KE_KEY, 0x13f, { KEY_SWITCHVIDEOMODE } },
  119. { KE_KEY, 0x140, { KEY_BRIGHTNESSDOWN } },
  120. { KE_KEY, 0x141, { KEY_BRIGHTNESSUP } },
  121. { KE_KEY, 0x142, { KEY_WLAN } },
  122. { KE_KEY, 0x143, { KEY_PROG1 } },
  123. { KE_KEY, 0xb05, { KEY_PROG2 } },
  124. { KE_KEY, 0xb06, { KEY_WWW } },
  125. { KE_KEY, 0xb07, { KEY_MAIL } },
  126. { KE_KEY, 0xb30, { KEY_STOP } },
  127. { KE_KEY, 0xb31, { KEY_PREVIOUSSONG } },
  128. { KE_KEY, 0xb32, { KEY_NEXTSONG } },
  129. { KE_KEY, 0xb33, { KEY_PLAYPAUSE } },
  130. { KE_KEY, 0xb5a, { KEY_MEDIA } },
  131. { KE_END, 0 },
  132. };
  133. /* utility
  134. */
  135. static __inline__ void _set_bit(u32 * word, u32 mask, int value)
  136. {
  137. *word = (*word & ~mask) | (mask * value);
  138. }
  139. /* acpi interface wrappers
  140. */
  141. static int is_valid_acpi_path(const char *methodName)
  142. {
  143. acpi_handle handle;
  144. acpi_status status;
  145. status = acpi_get_handle(NULL, (char *)methodName, &handle);
  146. return !ACPI_FAILURE(status);
  147. }
  148. static int write_acpi_int(const char *methodName, int val)
  149. {
  150. struct acpi_object_list params;
  151. union acpi_object in_objs[1];
  152. acpi_status status;
  153. params.count = ARRAY_SIZE(in_objs);
  154. params.pointer = in_objs;
  155. in_objs[0].type = ACPI_TYPE_INTEGER;
  156. in_objs[0].integer.value = val;
  157. status = acpi_evaluate_object(NULL, (char *)methodName, &params, NULL);
  158. return (status == AE_OK);
  159. }
  160. #if 0
  161. static int read_acpi_int(const char *methodName, int *pVal)
  162. {
  163. struct acpi_buffer results;
  164. union acpi_object out_objs[1];
  165. acpi_status status;
  166. results.length = sizeof(out_objs);
  167. results.pointer = out_objs;
  168. status = acpi_evaluate_object(0, (char *)methodName, 0, &results);
  169. *pVal = out_objs[0].integer.value;
  170. return (status == AE_OK) && (out_objs[0].type == ACPI_TYPE_INTEGER);
  171. }
  172. #endif
  173. static const char *method_hci /*= 0*/ ;
  174. /* Perform a raw HCI call. Here we don't care about input or output buffer
  175. * format.
  176. */
  177. static acpi_status hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
  178. {
  179. struct acpi_object_list params;
  180. union acpi_object in_objs[HCI_WORDS];
  181. struct acpi_buffer results;
  182. union acpi_object out_objs[HCI_WORDS + 1];
  183. acpi_status status;
  184. int i;
  185. params.count = HCI_WORDS;
  186. params.pointer = in_objs;
  187. for (i = 0; i < HCI_WORDS; ++i) {
  188. in_objs[i].type = ACPI_TYPE_INTEGER;
  189. in_objs[i].integer.value = in[i];
  190. }
  191. results.length = sizeof(out_objs);
  192. results.pointer = out_objs;
  193. status = acpi_evaluate_object(NULL, (char *)method_hci, &params,
  194. &results);
  195. if ((status == AE_OK) && (out_objs->package.count <= HCI_WORDS)) {
  196. for (i = 0; i < out_objs->package.count; ++i) {
  197. out[i] = out_objs->package.elements[i].integer.value;
  198. }
  199. }
  200. return status;
  201. }
  202. /* common hci tasks (get or set one or two value)
  203. *
  204. * In addition to the ACPI status, the HCI system returns a result which
  205. * may be useful (such as "not supported").
  206. */
  207. static acpi_status hci_write1(u32 reg, u32 in1, u32 * result)
  208. {
  209. u32 in[HCI_WORDS] = { HCI_SET, reg, in1, 0, 0, 0 };
  210. u32 out[HCI_WORDS];
  211. acpi_status status = hci_raw(in, out);
  212. *result = (status == AE_OK) ? out[0] : HCI_FAILURE;
  213. return status;
  214. }
  215. static acpi_status hci_read1(u32 reg, u32 * out1, u32 * result)
  216. {
  217. u32 in[HCI_WORDS] = { HCI_GET, reg, 0, 0, 0, 0 };
  218. u32 out[HCI_WORDS];
  219. acpi_status status = hci_raw(in, out);
  220. *out1 = out[2];
  221. *result = (status == AE_OK) ? out[0] : HCI_FAILURE;
  222. return status;
  223. }
  224. static acpi_status hci_write2(u32 reg, u32 in1, u32 in2, u32 *result)
  225. {
  226. u32 in[HCI_WORDS] = { HCI_SET, reg, in1, in2, 0, 0 };
  227. u32 out[HCI_WORDS];
  228. acpi_status status = hci_raw(in, out);
  229. *result = (status == AE_OK) ? out[0] : HCI_FAILURE;
  230. return status;
  231. }
  232. static acpi_status hci_read2(u32 reg, u32 *out1, u32 *out2, u32 *result)
  233. {
  234. u32 in[HCI_WORDS] = { HCI_GET, reg, *out1, *out2, 0, 0 };
  235. u32 out[HCI_WORDS];
  236. acpi_status status = hci_raw(in, out);
  237. *out1 = out[2];
  238. *out2 = out[3];
  239. *result = (status == AE_OK) ? out[0] : HCI_FAILURE;
  240. return status;
  241. }
  242. struct toshiba_acpi_dev {
  243. struct platform_device *p_dev;
  244. struct rfkill *bt_rfk;
  245. struct input_dev *hotkey_dev;
  246. int illumination_installed;
  247. acpi_handle handle;
  248. const char *bt_name;
  249. struct mutex mutex;
  250. };
  251. /* Illumination support */
  252. static int toshiba_illumination_available(void)
  253. {
  254. u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
  255. u32 out[HCI_WORDS];
  256. acpi_status status;
  257. in[0] = 0xf100;
  258. status = hci_raw(in, out);
  259. if (ACPI_FAILURE(status)) {
  260. printk(MY_INFO "Illumination device not available\n");
  261. return 0;
  262. }
  263. in[0] = 0xf400;
  264. status = hci_raw(in, out);
  265. return 1;
  266. }
  267. static void toshiba_illumination_set(struct led_classdev *cdev,
  268. enum led_brightness brightness)
  269. {
  270. u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
  271. u32 out[HCI_WORDS];
  272. acpi_status status;
  273. /* First request : initialize communication. */
  274. in[0] = 0xf100;
  275. status = hci_raw(in, out);
  276. if (ACPI_FAILURE(status)) {
  277. printk(MY_INFO "Illumination device not available\n");
  278. return;
  279. }
  280. if (brightness) {
  281. /* Switch the illumination on */
  282. in[0] = 0xf400;
  283. in[1] = 0x14e;
  284. in[2] = 1;
  285. status = hci_raw(in, out);
  286. if (ACPI_FAILURE(status)) {
  287. printk(MY_INFO "ACPI call for illumination failed.\n");
  288. return;
  289. }
  290. } else {
  291. /* Switch the illumination off */
  292. in[0] = 0xf400;
  293. in[1] = 0x14e;
  294. in[2] = 0;
  295. status = hci_raw(in, out);
  296. if (ACPI_FAILURE(status)) {
  297. printk(MY_INFO "ACPI call for illumination failed.\n");
  298. return;
  299. }
  300. }
  301. /* Last request : close communication. */
  302. in[0] = 0xf200;
  303. in[1] = 0;
  304. in[2] = 0;
  305. hci_raw(in, out);
  306. }
  307. static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev)
  308. {
  309. u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
  310. u32 out[HCI_WORDS];
  311. acpi_status status;
  312. enum led_brightness result;
  313. /* First request : initialize communication. */
  314. in[0] = 0xf100;
  315. status = hci_raw(in, out);
  316. if (ACPI_FAILURE(status)) {
  317. printk(MY_INFO "Illumination device not available\n");
  318. return LED_OFF;
  319. }
  320. /* Check the illumination */
  321. in[0] = 0xf300;
  322. in[1] = 0x14e;
  323. status = hci_raw(in, out);
  324. if (ACPI_FAILURE(status)) {
  325. printk(MY_INFO "ACPI call for illumination failed.\n");
  326. return LED_OFF;
  327. }
  328. result = out[2] ? LED_FULL : LED_OFF;
  329. /* Last request : close communication. */
  330. in[0] = 0xf200;
  331. in[1] = 0;
  332. in[2] = 0;
  333. hci_raw(in, out);
  334. return result;
  335. }
  336. static struct led_classdev toshiba_led = {
  337. .name = "toshiba::illumination",
  338. .max_brightness = 1,
  339. .brightness_set = toshiba_illumination_set,
  340. .brightness_get = toshiba_illumination_get,
  341. };
  342. static struct toshiba_acpi_dev toshiba_acpi = {
  343. .bt_name = "Toshiba Bluetooth",
  344. };
  345. /* Bluetooth rfkill handlers */
  346. static u32 hci_get_bt_present(bool *present)
  347. {
  348. u32 hci_result;
  349. u32 value, value2;
  350. value = 0;
  351. value2 = 0;
  352. hci_read2(HCI_WIRELESS, &value, &value2, &hci_result);
  353. if (hci_result == HCI_SUCCESS)
  354. *present = (value & HCI_WIRELESS_BT_PRESENT) ? true : false;
  355. return hci_result;
  356. }
  357. static u32 hci_get_radio_state(bool *radio_state)
  358. {
  359. u32 hci_result;
  360. u32 value, value2;
  361. value = 0;
  362. value2 = 0x0001;
  363. hci_read2(HCI_WIRELESS, &value, &value2, &hci_result);
  364. *radio_state = value & HCI_WIRELESS_KILL_SWITCH;
  365. return hci_result;
  366. }
  367. static int bt_rfkill_set_block(void *data, bool blocked)
  368. {
  369. struct toshiba_acpi_dev *dev = data;
  370. u32 result1, result2;
  371. u32 value;
  372. int err;
  373. bool radio_state;
  374. value = (blocked == false);
  375. mutex_lock(&dev->mutex);
  376. if (hci_get_radio_state(&radio_state) != HCI_SUCCESS) {
  377. err = -EBUSY;
  378. goto out;
  379. }
  380. if (!radio_state) {
  381. err = 0;
  382. goto out;
  383. }
  384. hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_POWER, &result1);
  385. hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_ATTACH, &result2);
  386. if (result1 != HCI_SUCCESS || result2 != HCI_SUCCESS)
  387. err = -EBUSY;
  388. else
  389. err = 0;
  390. out:
  391. mutex_unlock(&dev->mutex);
  392. return err;
  393. }
  394. static void bt_rfkill_poll(struct rfkill *rfkill, void *data)
  395. {
  396. bool new_rfk_state;
  397. bool value;
  398. u32 hci_result;
  399. struct toshiba_acpi_dev *dev = data;
  400. mutex_lock(&dev->mutex);
  401. hci_result = hci_get_radio_state(&value);
  402. if (hci_result != HCI_SUCCESS) {
  403. /* Can't do anything useful */
  404. mutex_unlock(&dev->mutex);
  405. return;
  406. }
  407. new_rfk_state = value;
  408. mutex_unlock(&dev->mutex);
  409. if (rfkill_set_hw_state(rfkill, !new_rfk_state))
  410. bt_rfkill_set_block(data, true);
  411. }
  412. static const struct rfkill_ops toshiba_rfk_ops = {
  413. .set_block = bt_rfkill_set_block,
  414. .poll = bt_rfkill_poll,
  415. };
  416. static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ;
  417. static struct backlight_device *toshiba_backlight_device;
  418. static int force_fan;
  419. static int last_key_event;
  420. static int key_event_valid;
  421. static int get_lcd(struct backlight_device *bd)
  422. {
  423. u32 hci_result;
  424. u32 value;
  425. hci_read1(HCI_LCD_BRIGHTNESS, &value, &hci_result);
  426. if (hci_result == HCI_SUCCESS) {
  427. return (value >> HCI_LCD_BRIGHTNESS_SHIFT);
  428. } else
  429. return -EFAULT;
  430. }
  431. static int lcd_proc_show(struct seq_file *m, void *v)
  432. {
  433. int value = get_lcd(NULL);
  434. if (value >= 0) {
  435. seq_printf(m, "brightness: %d\n", value);
  436. seq_printf(m, "brightness_levels: %d\n",
  437. HCI_LCD_BRIGHTNESS_LEVELS);
  438. } else {
  439. printk(MY_ERR "Error reading LCD brightness\n");
  440. }
  441. return 0;
  442. }
  443. static int lcd_proc_open(struct inode *inode, struct file *file)
  444. {
  445. return single_open(file, lcd_proc_show, NULL);
  446. }
  447. static int set_lcd(int value)
  448. {
  449. u32 hci_result;
  450. value = value << HCI_LCD_BRIGHTNESS_SHIFT;
  451. hci_write1(HCI_LCD_BRIGHTNESS, value, &hci_result);
  452. if (hci_result != HCI_SUCCESS)
  453. return -EFAULT;
  454. return 0;
  455. }
  456. static int set_lcd_status(struct backlight_device *bd)
  457. {
  458. return set_lcd(bd->props.brightness);
  459. }
  460. static ssize_t lcd_proc_write(struct file *file, const char __user *buf,
  461. size_t count, loff_t *pos)
  462. {
  463. char cmd[42];
  464. size_t len;
  465. int value;
  466. int ret;
  467. len = min(count, sizeof(cmd) - 1);
  468. if (copy_from_user(cmd, buf, len))
  469. return -EFAULT;
  470. cmd[len] = '\0';
  471. if (sscanf(cmd, " brightness : %i", &value) == 1 &&
  472. value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) {
  473. ret = set_lcd(value);
  474. if (ret == 0)
  475. ret = count;
  476. } else {
  477. ret = -EINVAL;
  478. }
  479. return ret;
  480. }
  481. static const struct file_operations lcd_proc_fops = {
  482. .owner = THIS_MODULE,
  483. .open = lcd_proc_open,
  484. .read = seq_read,
  485. .llseek = seq_lseek,
  486. .release = single_release,
  487. .write = lcd_proc_write,
  488. };
  489. static int video_proc_show(struct seq_file *m, void *v)
  490. {
  491. u32 hci_result;
  492. u32 value;
  493. hci_read1(HCI_VIDEO_OUT, &value, &hci_result);
  494. if (hci_result == HCI_SUCCESS) {
  495. int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0;
  496. int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0;
  497. int is_tv = (value & HCI_VIDEO_OUT_TV) ? 1 : 0;
  498. seq_printf(m, "lcd_out: %d\n", is_lcd);
  499. seq_printf(m, "crt_out: %d\n", is_crt);
  500. seq_printf(m, "tv_out: %d\n", is_tv);
  501. } else {
  502. printk(MY_ERR "Error reading video out status\n");
  503. }
  504. return 0;
  505. }
  506. static int video_proc_open(struct inode *inode, struct file *file)
  507. {
  508. return single_open(file, video_proc_show, NULL);
  509. }
  510. static ssize_t video_proc_write(struct file *file, const char __user *buf,
  511. size_t count, loff_t *pos)
  512. {
  513. char *cmd, *buffer;
  514. int value;
  515. int remain = count;
  516. int lcd_out = -1;
  517. int crt_out = -1;
  518. int tv_out = -1;
  519. u32 hci_result;
  520. u32 video_out;
  521. cmd = kmalloc(count + 1, GFP_KERNEL);
  522. if (!cmd)
  523. return -ENOMEM;
  524. if (copy_from_user(cmd, buf, count)) {
  525. kfree(cmd);
  526. return -EFAULT;
  527. }
  528. cmd[count] = '\0';
  529. buffer = cmd;
  530. /* scan expression. Multiple expressions may be delimited with ;
  531. *
  532. * NOTE: to keep scanning simple, invalid fields are ignored
  533. */
  534. while (remain) {
  535. if (sscanf(buffer, " lcd_out : %i", &value) == 1)
  536. lcd_out = value & 1;
  537. else if (sscanf(buffer, " crt_out : %i", &value) == 1)
  538. crt_out = value & 1;
  539. else if (sscanf(buffer, " tv_out : %i", &value) == 1)
  540. tv_out = value & 1;
  541. /* advance to one character past the next ; */
  542. do {
  543. ++buffer;
  544. --remain;
  545. }
  546. while (remain && *(buffer - 1) != ';');
  547. }
  548. kfree(cmd);
  549. hci_read1(HCI_VIDEO_OUT, &video_out, &hci_result);
  550. if (hci_result == HCI_SUCCESS) {
  551. unsigned int new_video_out = video_out;
  552. if (lcd_out != -1)
  553. _set_bit(&new_video_out, HCI_VIDEO_OUT_LCD, lcd_out);
  554. if (crt_out != -1)
  555. _set_bit(&new_video_out, HCI_VIDEO_OUT_CRT, crt_out);
  556. if (tv_out != -1)
  557. _set_bit(&new_video_out, HCI_VIDEO_OUT_TV, tv_out);
  558. /* To avoid unnecessary video disruption, only write the new
  559. * video setting if something changed. */
  560. if (new_video_out != video_out)
  561. write_acpi_int(METHOD_VIDEO_OUT, new_video_out);
  562. } else {
  563. return -EFAULT;
  564. }
  565. return count;
  566. }
  567. static const struct file_operations video_proc_fops = {
  568. .owner = THIS_MODULE,
  569. .open = video_proc_open,
  570. .read = seq_read,
  571. .llseek = seq_lseek,
  572. .release = single_release,
  573. .write = video_proc_write,
  574. };
  575. static int fan_proc_show(struct seq_file *m, void *v)
  576. {
  577. u32 hci_result;
  578. u32 value;
  579. hci_read1(HCI_FAN, &value, &hci_result);
  580. if (hci_result == HCI_SUCCESS) {
  581. seq_printf(m, "running: %d\n", (value > 0));
  582. seq_printf(m, "force_on: %d\n", force_fan);
  583. } else {
  584. printk(MY_ERR "Error reading fan status\n");
  585. }
  586. return 0;
  587. }
  588. static int fan_proc_open(struct inode *inode, struct file *file)
  589. {
  590. return single_open(file, fan_proc_show, NULL);
  591. }
  592. static ssize_t fan_proc_write(struct file *file, const char __user *buf,
  593. size_t count, loff_t *pos)
  594. {
  595. char cmd[42];
  596. size_t len;
  597. int value;
  598. u32 hci_result;
  599. len = min(count, sizeof(cmd) - 1);
  600. if (copy_from_user(cmd, buf, len))
  601. return -EFAULT;
  602. cmd[len] = '\0';
  603. if (sscanf(cmd, " force_on : %i", &value) == 1 &&
  604. value >= 0 && value <= 1) {
  605. hci_write1(HCI_FAN, value, &hci_result);
  606. if (hci_result != HCI_SUCCESS)
  607. return -EFAULT;
  608. else
  609. force_fan = value;
  610. } else {
  611. return -EINVAL;
  612. }
  613. return count;
  614. }
  615. static const struct file_operations fan_proc_fops = {
  616. .owner = THIS_MODULE,
  617. .open = fan_proc_open,
  618. .read = seq_read,
  619. .llseek = seq_lseek,
  620. .release = single_release,
  621. .write = fan_proc_write,
  622. };
  623. static int keys_proc_show(struct seq_file *m, void *v)
  624. {
  625. u32 hci_result;
  626. u32 value;
  627. if (!key_event_valid) {
  628. hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result);
  629. if (hci_result == HCI_SUCCESS) {
  630. key_event_valid = 1;
  631. last_key_event = value;
  632. } else if (hci_result == HCI_EMPTY) {
  633. /* better luck next time */
  634. } else if (hci_result == HCI_NOT_SUPPORTED) {
  635. /* This is a workaround for an unresolved issue on
  636. * some machines where system events sporadically
  637. * become disabled. */
  638. hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
  639. printk(MY_NOTICE "Re-enabled hotkeys\n");
  640. } else {
  641. printk(MY_ERR "Error reading hotkey status\n");
  642. goto end;
  643. }
  644. }
  645. seq_printf(m, "hotkey_ready: %d\n", key_event_valid);
  646. seq_printf(m, "hotkey: 0x%04x\n", last_key_event);
  647. end:
  648. return 0;
  649. }
  650. static int keys_proc_open(struct inode *inode, struct file *file)
  651. {
  652. return single_open(file, keys_proc_show, NULL);
  653. }
  654. static ssize_t keys_proc_write(struct file *file, const char __user *buf,
  655. size_t count, loff_t *pos)
  656. {
  657. char cmd[42];
  658. size_t len;
  659. int value;
  660. len = min(count, sizeof(cmd) - 1);
  661. if (copy_from_user(cmd, buf, len))
  662. return -EFAULT;
  663. cmd[len] = '\0';
  664. if (sscanf(cmd, " hotkey_ready : %i", &value) == 1 && value == 0) {
  665. key_event_valid = 0;
  666. } else {
  667. return -EINVAL;
  668. }
  669. return count;
  670. }
  671. static const struct file_operations keys_proc_fops = {
  672. .owner = THIS_MODULE,
  673. .open = keys_proc_open,
  674. .read = seq_read,
  675. .llseek = seq_lseek,
  676. .release = single_release,
  677. .write = keys_proc_write,
  678. };
  679. static int version_proc_show(struct seq_file *m, void *v)
  680. {
  681. seq_printf(m, "driver: %s\n", TOSHIBA_ACPI_VERSION);
  682. seq_printf(m, "proc_interface: %d\n", PROC_INTERFACE_VERSION);
  683. return 0;
  684. }
  685. static int version_proc_open(struct inode *inode, struct file *file)
  686. {
  687. return single_open(file, version_proc_show, PDE(inode)->data);
  688. }
  689. static const struct file_operations version_proc_fops = {
  690. .owner = THIS_MODULE,
  691. .open = version_proc_open,
  692. .read = seq_read,
  693. .llseek = seq_lseek,
  694. .release = single_release,
  695. };
  696. /* proc and module init
  697. */
  698. #define PROC_TOSHIBA "toshiba"
  699. static void __init create_toshiba_proc_entries(void)
  700. {
  701. proc_create("lcd", S_IRUGO | S_IWUSR, toshiba_proc_dir, &lcd_proc_fops);
  702. proc_create("video", S_IRUGO | S_IWUSR, toshiba_proc_dir, &video_proc_fops);
  703. proc_create("fan", S_IRUGO | S_IWUSR, toshiba_proc_dir, &fan_proc_fops);
  704. proc_create("keys", S_IRUGO | S_IWUSR, toshiba_proc_dir, &keys_proc_fops);
  705. proc_create("version", S_IRUGO, toshiba_proc_dir, &version_proc_fops);
  706. }
  707. static void remove_toshiba_proc_entries(void)
  708. {
  709. remove_proc_entry("lcd", toshiba_proc_dir);
  710. remove_proc_entry("video", toshiba_proc_dir);
  711. remove_proc_entry("fan", toshiba_proc_dir);
  712. remove_proc_entry("keys", toshiba_proc_dir);
  713. remove_proc_entry("version", toshiba_proc_dir);
  714. }
  715. static struct backlight_ops toshiba_backlight_data = {
  716. .get_brightness = get_lcd,
  717. .update_status = set_lcd_status,
  718. };
  719. static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context)
  720. {
  721. u32 hci_result, value;
  722. if (event != 0x80)
  723. return;
  724. do {
  725. hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result);
  726. if (hci_result == HCI_SUCCESS) {
  727. if (value == 0x100)
  728. continue;
  729. /* act on key press; ignore key release */
  730. if (value & 0x80)
  731. continue;
  732. if (!sparse_keymap_report_event(toshiba_acpi.hotkey_dev,
  733. value, 1, true)) {
  734. printk(MY_INFO "Unknown key %x\n",
  735. value);
  736. }
  737. } else if (hci_result == HCI_NOT_SUPPORTED) {
  738. /* This is a workaround for an unresolved issue on
  739. * some machines where system events sporadically
  740. * become disabled. */
  741. hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
  742. printk(MY_NOTICE "Re-enabled hotkeys\n");
  743. }
  744. } while (hci_result != HCI_EMPTY);
  745. }
  746. static int __init toshiba_acpi_setup_keyboard(char *device)
  747. {
  748. acpi_status status;
  749. int error;
  750. status = acpi_get_handle(NULL, device, &toshiba_acpi.handle);
  751. if (ACPI_FAILURE(status)) {
  752. printk(MY_INFO "Unable to get notification device\n");
  753. return -ENODEV;
  754. }
  755. toshiba_acpi.hotkey_dev = input_allocate_device();
  756. if (!toshiba_acpi.hotkey_dev) {
  757. printk(MY_INFO "Unable to register input device\n");
  758. return -ENOMEM;
  759. }
  760. toshiba_acpi.hotkey_dev->name = "Toshiba input device";
  761. toshiba_acpi.hotkey_dev->phys = device;
  762. toshiba_acpi.hotkey_dev->id.bustype = BUS_HOST;
  763. error = sparse_keymap_setup(toshiba_acpi.hotkey_dev,
  764. toshiba_acpi_keymap, NULL);
  765. if (error)
  766. goto err_free_dev;
  767. status = acpi_install_notify_handler(toshiba_acpi.handle,
  768. ACPI_DEVICE_NOTIFY, toshiba_acpi_notify, NULL);
  769. if (ACPI_FAILURE(status)) {
  770. printk(MY_INFO "Unable to install hotkey notification\n");
  771. error = -ENODEV;
  772. goto err_free_keymap;
  773. }
  774. status = acpi_evaluate_object(toshiba_acpi.handle, "ENAB", NULL, NULL);
  775. if (ACPI_FAILURE(status)) {
  776. printk(MY_INFO "Unable to enable hotkeys\n");
  777. error = -ENODEV;
  778. goto err_remove_notify;
  779. }
  780. error = input_register_device(toshiba_acpi.hotkey_dev);
  781. if (error) {
  782. printk(MY_INFO "Unable to register input device\n");
  783. goto err_remove_notify;
  784. }
  785. return 0;
  786. err_remove_notify:
  787. acpi_remove_notify_handler(toshiba_acpi.handle,
  788. ACPI_DEVICE_NOTIFY, toshiba_acpi_notify);
  789. err_free_keymap:
  790. sparse_keymap_free(toshiba_acpi.hotkey_dev);
  791. err_free_dev:
  792. input_free_device(toshiba_acpi.hotkey_dev);
  793. toshiba_acpi.hotkey_dev = NULL;
  794. return error;
  795. }
  796. static void toshiba_acpi_exit(void)
  797. {
  798. if (toshiba_acpi.hotkey_dev) {
  799. acpi_remove_notify_handler(toshiba_acpi.handle,
  800. ACPI_DEVICE_NOTIFY, toshiba_acpi_notify);
  801. sparse_keymap_free(toshiba_acpi.hotkey_dev);
  802. input_unregister_device(toshiba_acpi.hotkey_dev);
  803. }
  804. if (toshiba_acpi.bt_rfk) {
  805. rfkill_unregister(toshiba_acpi.bt_rfk);
  806. rfkill_destroy(toshiba_acpi.bt_rfk);
  807. }
  808. if (toshiba_backlight_device)
  809. backlight_device_unregister(toshiba_backlight_device);
  810. remove_toshiba_proc_entries();
  811. if (toshiba_proc_dir)
  812. remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
  813. if (toshiba_acpi.illumination_installed)
  814. led_classdev_unregister(&toshiba_led);
  815. platform_device_unregister(toshiba_acpi.p_dev);
  816. return;
  817. }
  818. static int __init toshiba_acpi_init(void)
  819. {
  820. u32 hci_result;
  821. bool bt_present;
  822. int ret = 0;
  823. struct backlight_properties props;
  824. if (acpi_disabled)
  825. return -ENODEV;
  826. /* simple device detection: look for HCI method */
  827. if (is_valid_acpi_path(TOSH_INTERFACE_1 GHCI_METHOD)) {
  828. method_hci = TOSH_INTERFACE_1 GHCI_METHOD;
  829. if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_1))
  830. printk(MY_INFO "Unable to activate hotkeys\n");
  831. } else if (is_valid_acpi_path(TOSH_INTERFACE_2 GHCI_METHOD)) {
  832. method_hci = TOSH_INTERFACE_2 GHCI_METHOD;
  833. if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_2))
  834. printk(MY_INFO "Unable to activate hotkeys\n");
  835. } else
  836. return -ENODEV;
  837. printk(MY_INFO "Toshiba Laptop ACPI Extras version %s\n",
  838. TOSHIBA_ACPI_VERSION);
  839. printk(MY_INFO " HCI method: %s\n", method_hci);
  840. mutex_init(&toshiba_acpi.mutex);
  841. toshiba_acpi.p_dev = platform_device_register_simple("toshiba_acpi",
  842. -1, NULL, 0);
  843. if (IS_ERR(toshiba_acpi.p_dev)) {
  844. ret = PTR_ERR(toshiba_acpi.p_dev);
  845. printk(MY_ERR "unable to register platform device\n");
  846. toshiba_acpi.p_dev = NULL;
  847. toshiba_acpi_exit();
  848. return ret;
  849. }
  850. force_fan = 0;
  851. key_event_valid = 0;
  852. /* enable event fifo */
  853. hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
  854. toshiba_proc_dir = proc_mkdir(PROC_TOSHIBA, acpi_root_dir);
  855. if (!toshiba_proc_dir) {
  856. toshiba_acpi_exit();
  857. return -ENODEV;
  858. } else {
  859. create_toshiba_proc_entries();
  860. }
  861. props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
  862. toshiba_backlight_device = backlight_device_register("toshiba",
  863. &toshiba_acpi.p_dev->dev,
  864. NULL,
  865. &toshiba_backlight_data,
  866. &props);
  867. if (IS_ERR(toshiba_backlight_device)) {
  868. ret = PTR_ERR(toshiba_backlight_device);
  869. printk(KERN_ERR "Could not register toshiba backlight device\n");
  870. toshiba_backlight_device = NULL;
  871. toshiba_acpi_exit();
  872. return ret;
  873. }
  874. /* Register rfkill switch for Bluetooth */
  875. if (hci_get_bt_present(&bt_present) == HCI_SUCCESS && bt_present) {
  876. toshiba_acpi.bt_rfk = rfkill_alloc(toshiba_acpi.bt_name,
  877. &toshiba_acpi.p_dev->dev,
  878. RFKILL_TYPE_BLUETOOTH,
  879. &toshiba_rfk_ops,
  880. &toshiba_acpi);
  881. if (!toshiba_acpi.bt_rfk) {
  882. printk(MY_ERR "unable to allocate rfkill device\n");
  883. toshiba_acpi_exit();
  884. return -ENOMEM;
  885. }
  886. ret = rfkill_register(toshiba_acpi.bt_rfk);
  887. if (ret) {
  888. printk(MY_ERR "unable to register rfkill device\n");
  889. rfkill_destroy(toshiba_acpi.bt_rfk);
  890. toshiba_acpi_exit();
  891. return ret;
  892. }
  893. }
  894. toshiba_acpi.illumination_installed = 0;
  895. if (toshiba_illumination_available()) {
  896. if (!led_classdev_register(&(toshiba_acpi.p_dev->dev),
  897. &toshiba_led))
  898. toshiba_acpi.illumination_installed = 1;
  899. }
  900. return 0;
  901. }
  902. module_init(toshiba_acpi_init);
  903. module_exit(toshiba_acpi_exit);