panasonic-laptop.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Panasonic HotKey and LCD brightness control driver
  4. * (C) 2004 Hiroshi Miura <[email protected]>
  5. * (C) 2004 NTT DATA Intellilink Co. http://www.intellilink.co.jp/
  6. * (C) YOKOTA Hiroshi <yokota (at) netlab. is. tsukuba. ac. jp>
  7. * (C) 2004 David Bronaugh <dbronaugh>
  8. * (C) 2006-2008 Harald Welte <[email protected]>
  9. *
  10. * derived from toshiba_acpi.c, Copyright (C) 2002-2004 John Belmonte
  11. *
  12. *---------------------------------------------------------------------------
  13. *
  14. * ChangeLog:
  15. * Aug.18, 2020 Kenneth Chan <[email protected]>
  16. * -v0.98 add platform devices for firmware brightness registers
  17. * add support for battery charging threshold (eco mode)
  18. * resolve hotkey double trigger
  19. * add write support to mute
  20. * fix sticky_key init bug
  21. * fix naming of platform files for consistency with other
  22. * modules
  23. * split MODULE_AUTHOR() by one author per macro call
  24. * replace ACPI prints with pr_*() macros
  25. * -v0.97 add support for cdpower hardware switch
  26. * -v0.96 merge Lucina's enhancement
  27. * Jan.13, 2009 Martin Lucina <[email protected]>
  28. * - add support for optical driver power in
  29. * Y and W series
  30. *
  31. * Sep.23, 2008 Harald Welte <[email protected]>
  32. * -v0.95 rename driver from drivers/acpi/pcc_acpi.c to
  33. * drivers/misc/panasonic-laptop.c
  34. *
  35. * Jul.04, 2008 Harald Welte <[email protected]>
  36. * -v0.94 replace /proc interface with device attributes
  37. * support {set,get}keycode on th input device
  38. *
  39. * Jun.27, 2008 Harald Welte <[email protected]>
  40. * -v0.92 merge with 2.6.26-rc6 input API changes
  41. * remove broken <= 2.6.15 kernel support
  42. * resolve all compiler warnings
  43. * various coding style fixes (checkpatch.pl)
  44. * add support for backlight api
  45. * major code restructuring
  46. *
  47. * Dac.28, 2007 Harald Welte <[email protected]>
  48. * -v0.91 merge with 2.6.24-rc6 ACPI changes
  49. *
  50. * Nov.04, 2006 Hiroshi Miura <[email protected]>
  51. * -v0.9 remove warning about section reference.
  52. * remove acpi_os_free
  53. * add /proc/acpi/pcc/brightness interface for HAL access
  54. * merge dbronaugh's enhancement
  55. * Aug.17, 2004 David Bronaugh (dbronaugh)
  56. * - Added screen brightness setting interface
  57. * Thanks to FreeBSD crew (acpi_panasonic.c)
  58. * for the ideas I needed to accomplish it
  59. *
  60. * May.29, 2006 Hiroshi Miura <[email protected]>
  61. * -v0.8.4 follow to change keyinput structure
  62. * thanks Fabian Yamaguchi <[email protected]>,
  63. * Jacob Bower <[email protected]> and
  64. * Hiroshi Yokota for providing solutions.
  65. *
  66. * Oct.02, 2004 Hiroshi Miura <[email protected]>
  67. * -v0.8.2 merge code of YOKOTA Hiroshi
  68. * <[email protected]>.
  69. * Add sticky key mode interface.
  70. * Refactoring acpi_pcc_generate_keyinput().
  71. *
  72. * Sep.15, 2004 Hiroshi Miura <[email protected]>
  73. * -v0.8 Generate key input event on input subsystem.
  74. * This is based on yet another driver written by
  75. * Ryuta Nakanishi.
  76. *
  77. * Sep.10, 2004 Hiroshi Miura <[email protected]>
  78. * -v0.7 Change proc interface functions using seq_file
  79. * facility as same as other ACPI drivers.
  80. *
  81. * Aug.28, 2004 Hiroshi Miura <[email protected]>
  82. * -v0.6.4 Fix a silly error with status checking
  83. *
  84. * Aug.25, 2004 Hiroshi Miura <[email protected]>
  85. * -v0.6.3 replace read_acpi_int by standard function
  86. * acpi_evaluate_integer
  87. * some clean up and make smart copyright notice.
  88. * fix return value of pcc_acpi_get_key()
  89. * fix checking return value of acpi_bus_register_driver()
  90. *
  91. * Aug.22, 2004 David Bronaugh <[email protected]>
  92. * -v0.6.2 Add check on ACPI data (num_sifr)
  93. * Coding style cleanups, better error messages/handling
  94. * Fixed an off-by-one error in memory allocation
  95. *
  96. * Aug.21, 2004 David Bronaugh <[email protected]>
  97. * -v0.6.1 Fix a silly error with status checking
  98. *
  99. * Aug.20, 2004 David Bronaugh <[email protected]>
  100. * - v0.6 Correct brightness controls to reflect reality
  101. * based on information gleaned by Hiroshi Miura
  102. * and discussions with Hiroshi Miura
  103. *
  104. * Aug.10, 2004 Hiroshi Miura <[email protected]>
  105. * - v0.5 support LCD brightness control
  106. * based on the disclosed information by MEI.
  107. *
  108. * Jul.25, 2004 Hiroshi Miura <[email protected]>
  109. * - v0.4 first post version
  110. * add function to retrive SIFR
  111. *
  112. * Jul.24, 2004 Hiroshi Miura <[email protected]>
  113. * - v0.3 get proper status of hotkey
  114. *
  115. * Jul.22, 2004 Hiroshi Miura <[email protected]>
  116. * - v0.2 add HotKey handler
  117. *
  118. * Jul.17, 2004 Hiroshi Miura <[email protected]>
  119. * - v0.1 start from toshiba_acpi driver written by John Belmonte
  120. */
  121. #include <linux/acpi.h>
  122. #include <linux/backlight.h>
  123. #include <linux/ctype.h>
  124. #include <linux/i8042.h>
  125. #include <linux/init.h>
  126. #include <linux/input.h>
  127. #include <linux/input/sparse-keymap.h>
  128. #include <linux/kernel.h>
  129. #include <linux/module.h>
  130. #include <linux/platform_device.h>
  131. #include <linux/seq_file.h>
  132. #include <linux/serio.h>
  133. #include <linux/slab.h>
  134. #include <linux/types.h>
  135. #include <linux/uaccess.h>
  136. #include <acpi/video.h>
  137. MODULE_AUTHOR("Hiroshi Miura <[email protected]>");
  138. MODULE_AUTHOR("David Bronaugh <[email protected]>");
  139. MODULE_AUTHOR("Harald Welte <[email protected]>");
  140. MODULE_AUTHOR("Martin Lucina <[email protected]>");
  141. MODULE_AUTHOR("Kenneth Chan <[email protected]>");
  142. MODULE_DESCRIPTION("ACPI HotKey driver for Panasonic Let's Note laptops");
  143. MODULE_LICENSE("GPL");
  144. #define LOGPREFIX "pcc_acpi: "
  145. /* Define ACPI PATHs */
  146. /* Lets note hotkeys */
  147. #define METHOD_HKEY_QUERY "HINF"
  148. #define METHOD_HKEY_SQTY "SQTY"
  149. #define METHOD_HKEY_SINF "SINF"
  150. #define METHOD_HKEY_SSET "SSET"
  151. #define METHOD_ECWR "\\_SB.ECWR"
  152. #define HKEY_NOTIFY 0x80
  153. #define ECO_MODE_OFF 0x00
  154. #define ECO_MODE_ON 0x80
  155. #define ACPI_PCC_DRIVER_NAME "Panasonic Laptop Support"
  156. #define ACPI_PCC_DEVICE_NAME "Hotkey"
  157. #define ACPI_PCC_CLASS "pcc"
  158. #define ACPI_PCC_INPUT_PHYS "panasonic/hkey0"
  159. /* LCD_TYPEs: 0 = Normal, 1 = Semi-transparent
  160. ECO_MODEs: 0x03 = off, 0x83 = on
  161. */
  162. enum SINF_BITS { SINF_NUM_BATTERIES = 0,
  163. SINF_LCD_TYPE,
  164. SINF_AC_MAX_BRIGHT,
  165. SINF_AC_MIN_BRIGHT,
  166. SINF_AC_CUR_BRIGHT,
  167. SINF_DC_MAX_BRIGHT,
  168. SINF_DC_MIN_BRIGHT,
  169. SINF_DC_CUR_BRIGHT,
  170. SINF_MUTE,
  171. SINF_RESERVED,
  172. SINF_ECO_MODE = 0x0A,
  173. SINF_CUR_BRIGHT = 0x0D,
  174. SINF_STICKY_KEY = 0x80,
  175. };
  176. /* R1 handles SINF_AC_CUR_BRIGHT as SINF_CUR_BRIGHT, doesn't know AC state */
  177. static int acpi_pcc_hotkey_add(struct acpi_device *device);
  178. static int acpi_pcc_hotkey_remove(struct acpi_device *device);
  179. static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event);
  180. static const struct acpi_device_id pcc_device_ids[] = {
  181. { "MAT0012", 0},
  182. { "MAT0013", 0},
  183. { "MAT0018", 0},
  184. { "MAT0019", 0},
  185. { "", 0},
  186. };
  187. MODULE_DEVICE_TABLE(acpi, pcc_device_ids);
  188. #ifdef CONFIG_PM_SLEEP
  189. static int acpi_pcc_hotkey_resume(struct device *dev);
  190. #endif
  191. static SIMPLE_DEV_PM_OPS(acpi_pcc_hotkey_pm, NULL, acpi_pcc_hotkey_resume);
  192. static struct acpi_driver acpi_pcc_driver = {
  193. .name = ACPI_PCC_DRIVER_NAME,
  194. .class = ACPI_PCC_CLASS,
  195. .ids = pcc_device_ids,
  196. .ops = {
  197. .add = acpi_pcc_hotkey_add,
  198. .remove = acpi_pcc_hotkey_remove,
  199. .notify = acpi_pcc_hotkey_notify,
  200. },
  201. .drv.pm = &acpi_pcc_hotkey_pm,
  202. };
  203. static const struct key_entry panasonic_keymap[] = {
  204. { KE_KEY, 0, { KEY_RESERVED } },
  205. { KE_KEY, 1, { KEY_BRIGHTNESSDOWN } },
  206. { KE_KEY, 2, { KEY_BRIGHTNESSUP } },
  207. { KE_KEY, 3, { KEY_DISPLAYTOGGLE } },
  208. { KE_KEY, 4, { KEY_MUTE } },
  209. { KE_KEY, 5, { KEY_VOLUMEDOWN } },
  210. { KE_KEY, 6, { KEY_VOLUMEUP } },
  211. { KE_KEY, 7, { KEY_SLEEP } },
  212. { KE_KEY, 8, { KEY_PROG1 } }, /* Change CPU boost */
  213. { KE_KEY, 9, { KEY_BATTERY } },
  214. { KE_KEY, 10, { KEY_SUSPEND } },
  215. { KE_END, 0 }
  216. };
  217. struct pcc_acpi {
  218. acpi_handle handle;
  219. unsigned long num_sifr;
  220. int sticky_key;
  221. int eco_mode;
  222. int mute;
  223. int ac_brightness;
  224. int dc_brightness;
  225. int current_brightness;
  226. u32 *sinf;
  227. struct acpi_device *device;
  228. struct input_dev *input_dev;
  229. struct backlight_device *backlight;
  230. struct platform_device *platform;
  231. };
  232. /*
  233. * On some Panasonic models the volume up / down / mute keys send duplicate
  234. * keypress events over the PS/2 kbd interface, filter these out.
  235. */
  236. static bool panasonic_i8042_filter(unsigned char data, unsigned char str,
  237. struct serio *port)
  238. {
  239. static bool extended;
  240. if (str & I8042_STR_AUXDATA)
  241. return false;
  242. if (data == 0xe0) {
  243. extended = true;
  244. return true;
  245. } else if (extended) {
  246. extended = false;
  247. switch (data & 0x7f) {
  248. case 0x20: /* e0 20 / e0 a0, Volume Mute press / release */
  249. case 0x2e: /* e0 2e / e0 ae, Volume Down press / release */
  250. case 0x30: /* e0 30 / e0 b0, Volume Up press / release */
  251. return true;
  252. default:
  253. /*
  254. * Report the previously filtered e0 before continuing
  255. * with the next non-filtered byte.
  256. */
  257. serio_interrupt(port, 0xe0, 0);
  258. return false;
  259. }
  260. }
  261. return false;
  262. }
  263. /* method access functions */
  264. static int acpi_pcc_write_sset(struct pcc_acpi *pcc, int func, int val)
  265. {
  266. union acpi_object in_objs[] = {
  267. { .integer.type = ACPI_TYPE_INTEGER,
  268. .integer.value = func, },
  269. { .integer.type = ACPI_TYPE_INTEGER,
  270. .integer.value = val, },
  271. };
  272. struct acpi_object_list params = {
  273. .count = ARRAY_SIZE(in_objs),
  274. .pointer = in_objs,
  275. };
  276. acpi_status status = AE_OK;
  277. status = acpi_evaluate_object(pcc->handle, METHOD_HKEY_SSET,
  278. &params, NULL);
  279. return (status == AE_OK) ? 0 : -EIO;
  280. }
  281. static inline int acpi_pcc_get_sqty(struct acpi_device *device)
  282. {
  283. unsigned long long s;
  284. acpi_status status;
  285. status = acpi_evaluate_integer(device->handle, METHOD_HKEY_SQTY,
  286. NULL, &s);
  287. if (ACPI_SUCCESS(status))
  288. return s;
  289. else {
  290. pr_err("evaluation error HKEY.SQTY\n");
  291. return -EINVAL;
  292. }
  293. }
  294. static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc)
  295. {
  296. acpi_status status;
  297. struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
  298. union acpi_object *hkey = NULL;
  299. int i;
  300. status = acpi_evaluate_object(pcc->handle, METHOD_HKEY_SINF, NULL,
  301. &buffer);
  302. if (ACPI_FAILURE(status)) {
  303. pr_err("evaluation error HKEY.SINF\n");
  304. return 0;
  305. }
  306. hkey = buffer.pointer;
  307. if (!hkey || (hkey->type != ACPI_TYPE_PACKAGE)) {
  308. pr_err("Invalid HKEY.SINF\n");
  309. status = AE_ERROR;
  310. goto end;
  311. }
  312. if (pcc->num_sifr < hkey->package.count) {
  313. pr_err("SQTY reports bad SINF length\n");
  314. status = AE_ERROR;
  315. goto end;
  316. }
  317. for (i = 0; i < hkey->package.count; i++) {
  318. union acpi_object *element = &(hkey->package.elements[i]);
  319. if (likely(element->type == ACPI_TYPE_INTEGER)) {
  320. pcc->sinf[i] = element->integer.value;
  321. } else
  322. pr_err("Invalid HKEY.SINF data\n");
  323. }
  324. pcc->sinf[hkey->package.count] = -1;
  325. end:
  326. kfree(buffer.pointer);
  327. return status == AE_OK;
  328. }
  329. /* backlight API interface functions */
  330. /* This driver currently treats AC and DC brightness identical,
  331. * since we don't need to invent an interface to the core ACPI
  332. * logic to receive events in case a power supply is plugged in
  333. * or removed */
  334. static int bl_get(struct backlight_device *bd)
  335. {
  336. struct pcc_acpi *pcc = bl_get_data(bd);
  337. if (!acpi_pcc_retrieve_biosdata(pcc))
  338. return -EIO;
  339. return pcc->sinf[SINF_AC_CUR_BRIGHT];
  340. }
  341. static int bl_set_status(struct backlight_device *bd)
  342. {
  343. struct pcc_acpi *pcc = bl_get_data(bd);
  344. int bright = bd->props.brightness;
  345. int rc;
  346. if (!acpi_pcc_retrieve_biosdata(pcc))
  347. return -EIO;
  348. if (bright < pcc->sinf[SINF_AC_MIN_BRIGHT])
  349. bright = pcc->sinf[SINF_AC_MIN_BRIGHT];
  350. if (bright < pcc->sinf[SINF_DC_MIN_BRIGHT])
  351. bright = pcc->sinf[SINF_DC_MIN_BRIGHT];
  352. if (bright < pcc->sinf[SINF_AC_MIN_BRIGHT] ||
  353. bright > pcc->sinf[SINF_AC_MAX_BRIGHT])
  354. return -EINVAL;
  355. rc = acpi_pcc_write_sset(pcc, SINF_AC_CUR_BRIGHT, bright);
  356. if (rc < 0)
  357. return rc;
  358. return acpi_pcc_write_sset(pcc, SINF_DC_CUR_BRIGHT, bright);
  359. }
  360. static const struct backlight_ops pcc_backlight_ops = {
  361. .get_brightness = bl_get,
  362. .update_status = bl_set_status,
  363. };
  364. /* returns ACPI_SUCCESS if methods to control optical drive are present */
  365. static acpi_status check_optd_present(void)
  366. {
  367. acpi_status status = AE_OK;
  368. acpi_handle handle;
  369. status = acpi_get_handle(NULL, "\\_SB.STAT", &handle);
  370. if (ACPI_FAILURE(status))
  371. goto out;
  372. status = acpi_get_handle(NULL, "\\_SB.FBAY", &handle);
  373. if (ACPI_FAILURE(status))
  374. goto out;
  375. status = acpi_get_handle(NULL, "\\_SB.CDDI", &handle);
  376. if (ACPI_FAILURE(status))
  377. goto out;
  378. out:
  379. return status;
  380. }
  381. /* get optical driver power state */
  382. static int get_optd_power_state(void)
  383. {
  384. acpi_status status;
  385. unsigned long long state;
  386. int result;
  387. status = acpi_evaluate_integer(NULL, "\\_SB.STAT", NULL, &state);
  388. if (ACPI_FAILURE(status)) {
  389. pr_err("evaluation error _SB.STAT\n");
  390. result = -EIO;
  391. goto out;
  392. }
  393. switch (state) {
  394. case 0: /* power off */
  395. result = 0;
  396. break;
  397. case 0x0f: /* power on */
  398. result = 1;
  399. break;
  400. default:
  401. result = -EIO;
  402. break;
  403. }
  404. out:
  405. return result;
  406. }
  407. /* set optical drive power state */
  408. static int set_optd_power_state(int new_state)
  409. {
  410. int result;
  411. acpi_status status;
  412. result = get_optd_power_state();
  413. if (result < 0)
  414. goto out;
  415. if (new_state == result)
  416. goto out;
  417. switch (new_state) {
  418. case 0: /* power off */
  419. /* Call CDDR instead, since they both call the same method
  420. * while CDDI takes 1 arg and we are not quite sure what it is.
  421. */
  422. status = acpi_evaluate_object(NULL, "\\_SB.CDDR", NULL, NULL);
  423. if (ACPI_FAILURE(status)) {
  424. pr_err("evaluation error _SB.CDDR\n");
  425. result = -EIO;
  426. }
  427. break;
  428. case 1: /* power on */
  429. status = acpi_evaluate_object(NULL, "\\_SB.FBAY", NULL, NULL);
  430. if (ACPI_FAILURE(status)) {
  431. pr_err("evaluation error _SB.FBAY\n");
  432. result = -EIO;
  433. }
  434. break;
  435. default:
  436. result = -EINVAL;
  437. break;
  438. }
  439. out:
  440. return result;
  441. }
  442. /* sysfs user interface functions */
  443. static ssize_t numbatt_show(struct device *dev, struct device_attribute *attr,
  444. char *buf)
  445. {
  446. struct acpi_device *acpi = to_acpi_device(dev);
  447. struct pcc_acpi *pcc = acpi_driver_data(acpi);
  448. if (!acpi_pcc_retrieve_biosdata(pcc))
  449. return -EIO;
  450. return sysfs_emit(buf, "%u\n", pcc->sinf[SINF_NUM_BATTERIES]);
  451. }
  452. static ssize_t lcdtype_show(struct device *dev, struct device_attribute *attr,
  453. char *buf)
  454. {
  455. struct acpi_device *acpi = to_acpi_device(dev);
  456. struct pcc_acpi *pcc = acpi_driver_data(acpi);
  457. if (!acpi_pcc_retrieve_biosdata(pcc))
  458. return -EIO;
  459. return sysfs_emit(buf, "%u\n", pcc->sinf[SINF_LCD_TYPE]);
  460. }
  461. static ssize_t mute_show(struct device *dev, struct device_attribute *attr,
  462. char *buf)
  463. {
  464. struct acpi_device *acpi = to_acpi_device(dev);
  465. struct pcc_acpi *pcc = acpi_driver_data(acpi);
  466. if (!acpi_pcc_retrieve_biosdata(pcc))
  467. return -EIO;
  468. return sysfs_emit(buf, "%u\n", pcc->sinf[SINF_MUTE]);
  469. }
  470. static ssize_t mute_store(struct device *dev, struct device_attribute *attr,
  471. const char *buf, size_t count)
  472. {
  473. struct acpi_device *acpi = to_acpi_device(dev);
  474. struct pcc_acpi *pcc = acpi_driver_data(acpi);
  475. int err, val;
  476. err = kstrtoint(buf, 0, &val);
  477. if (err)
  478. return err;
  479. if (val == 0 || val == 1) {
  480. acpi_pcc_write_sset(pcc, SINF_MUTE, val);
  481. pcc->mute = val;
  482. }
  483. return count;
  484. }
  485. static ssize_t sticky_key_show(struct device *dev, struct device_attribute *attr,
  486. char *buf)
  487. {
  488. struct acpi_device *acpi = to_acpi_device(dev);
  489. struct pcc_acpi *pcc = acpi_driver_data(acpi);
  490. if (!acpi_pcc_retrieve_biosdata(pcc))
  491. return -EIO;
  492. return sysfs_emit(buf, "%u\n", pcc->sticky_key);
  493. }
  494. static ssize_t sticky_key_store(struct device *dev, struct device_attribute *attr,
  495. const char *buf, size_t count)
  496. {
  497. struct acpi_device *acpi = to_acpi_device(dev);
  498. struct pcc_acpi *pcc = acpi_driver_data(acpi);
  499. int err, val;
  500. err = kstrtoint(buf, 0, &val);
  501. if (err)
  502. return err;
  503. if (val == 0 || val == 1) {
  504. acpi_pcc_write_sset(pcc, SINF_STICKY_KEY, val);
  505. pcc->sticky_key = val;
  506. }
  507. return count;
  508. }
  509. static ssize_t eco_mode_show(struct device *dev, struct device_attribute *attr,
  510. char *buf)
  511. {
  512. struct acpi_device *acpi = to_acpi_device(dev);
  513. struct pcc_acpi *pcc = acpi_driver_data(acpi);
  514. int result;
  515. if (!acpi_pcc_retrieve_biosdata(pcc))
  516. return -EIO;
  517. switch (pcc->sinf[SINF_ECO_MODE]) {
  518. case (ECO_MODE_OFF + 3):
  519. result = 0;
  520. break;
  521. case (ECO_MODE_ON + 3):
  522. result = 1;
  523. break;
  524. default:
  525. result = -EIO;
  526. break;
  527. }
  528. return sysfs_emit(buf, "%u\n", result);
  529. }
  530. static ssize_t eco_mode_store(struct device *dev, struct device_attribute *attr,
  531. const char *buf, size_t count)
  532. {
  533. struct acpi_device *acpi = to_acpi_device(dev);
  534. struct pcc_acpi *pcc = acpi_driver_data(acpi);
  535. int err, state;
  536. union acpi_object param[2];
  537. struct acpi_object_list input;
  538. acpi_status status;
  539. param[0].type = ACPI_TYPE_INTEGER;
  540. param[0].integer.value = 0x15;
  541. param[1].type = ACPI_TYPE_INTEGER;
  542. input.count = 2;
  543. input.pointer = param;
  544. err = kstrtoint(buf, 0, &state);
  545. if (err)
  546. return err;
  547. switch (state) {
  548. case 0:
  549. param[1].integer.value = ECO_MODE_OFF;
  550. pcc->sinf[SINF_ECO_MODE] = 0;
  551. pcc->eco_mode = 0;
  552. break;
  553. case 1:
  554. param[1].integer.value = ECO_MODE_ON;
  555. pcc->sinf[SINF_ECO_MODE] = 1;
  556. pcc->eco_mode = 1;
  557. break;
  558. default:
  559. /* nothing to do */
  560. return count;
  561. }
  562. status = acpi_evaluate_object(NULL, METHOD_ECWR,
  563. &input, NULL);
  564. if (ACPI_FAILURE(status)) {
  565. pr_err("%s evaluation failed\n", METHOD_ECWR);
  566. return -EINVAL;
  567. }
  568. return count;
  569. }
  570. static ssize_t ac_brightness_show(struct device *dev, struct device_attribute *attr,
  571. char *buf)
  572. {
  573. struct acpi_device *acpi = to_acpi_device(dev);
  574. struct pcc_acpi *pcc = acpi_driver_data(acpi);
  575. if (!acpi_pcc_retrieve_biosdata(pcc))
  576. return -EIO;
  577. return sysfs_emit(buf, "%u\n", pcc->sinf[SINF_AC_CUR_BRIGHT]);
  578. }
  579. static ssize_t ac_brightness_store(struct device *dev, struct device_attribute *attr,
  580. const char *buf, size_t count)
  581. {
  582. struct acpi_device *acpi = to_acpi_device(dev);
  583. struct pcc_acpi *pcc = acpi_driver_data(acpi);
  584. int err, val;
  585. err = kstrtoint(buf, 0, &val);
  586. if (err)
  587. return err;
  588. if (val >= 0 && val <= 255) {
  589. acpi_pcc_write_sset(pcc, SINF_AC_CUR_BRIGHT, val);
  590. pcc->ac_brightness = val;
  591. }
  592. return count;
  593. }
  594. static ssize_t dc_brightness_show(struct device *dev, struct device_attribute *attr,
  595. char *buf)
  596. {
  597. struct acpi_device *acpi = to_acpi_device(dev);
  598. struct pcc_acpi *pcc = acpi_driver_data(acpi);
  599. if (!acpi_pcc_retrieve_biosdata(pcc))
  600. return -EIO;
  601. return sysfs_emit(buf, "%u\n", pcc->sinf[SINF_DC_CUR_BRIGHT]);
  602. }
  603. static ssize_t dc_brightness_store(struct device *dev, struct device_attribute *attr,
  604. const char *buf, size_t count)
  605. {
  606. struct acpi_device *acpi = to_acpi_device(dev);
  607. struct pcc_acpi *pcc = acpi_driver_data(acpi);
  608. int err, val;
  609. err = kstrtoint(buf, 0, &val);
  610. if (err)
  611. return err;
  612. if (val >= 0 && val <= 255) {
  613. acpi_pcc_write_sset(pcc, SINF_DC_CUR_BRIGHT, val);
  614. pcc->dc_brightness = val;
  615. }
  616. return count;
  617. }
  618. static ssize_t current_brightness_show(struct device *dev, struct device_attribute *attr,
  619. char *buf)
  620. {
  621. struct acpi_device *acpi = to_acpi_device(dev);
  622. struct pcc_acpi *pcc = acpi_driver_data(acpi);
  623. if (!acpi_pcc_retrieve_biosdata(pcc))
  624. return -EIO;
  625. return sysfs_emit(buf, "%u\n", pcc->sinf[SINF_CUR_BRIGHT]);
  626. }
  627. static ssize_t current_brightness_store(struct device *dev, struct device_attribute *attr,
  628. const char *buf, size_t count)
  629. {
  630. struct acpi_device *acpi = to_acpi_device(dev);
  631. struct pcc_acpi *pcc = acpi_driver_data(acpi);
  632. int err, val;
  633. err = kstrtoint(buf, 0, &val);
  634. if (err)
  635. return err;
  636. if (val >= 0 && val <= 255) {
  637. err = acpi_pcc_write_sset(pcc, SINF_CUR_BRIGHT, val);
  638. pcc->current_brightness = val;
  639. }
  640. return count;
  641. }
  642. static ssize_t cdpower_show(struct device *dev, struct device_attribute *attr,
  643. char *buf)
  644. {
  645. return sysfs_emit(buf, "%d\n", get_optd_power_state());
  646. }
  647. static ssize_t cdpower_store(struct device *dev, struct device_attribute *attr,
  648. const char *buf, size_t count)
  649. {
  650. int err, val;
  651. err = kstrtoint(buf, 10, &val);
  652. if (err)
  653. return err;
  654. set_optd_power_state(val);
  655. return count;
  656. }
  657. static DEVICE_ATTR_RO(numbatt);
  658. static DEVICE_ATTR_RO(lcdtype);
  659. static DEVICE_ATTR_RW(mute);
  660. static DEVICE_ATTR_RW(sticky_key);
  661. static DEVICE_ATTR_RW(eco_mode);
  662. static DEVICE_ATTR_RW(ac_brightness);
  663. static DEVICE_ATTR_RW(dc_brightness);
  664. static DEVICE_ATTR_RW(current_brightness);
  665. static DEVICE_ATTR_RW(cdpower);
  666. static struct attribute *pcc_sysfs_entries[] = {
  667. &dev_attr_numbatt.attr,
  668. &dev_attr_lcdtype.attr,
  669. &dev_attr_mute.attr,
  670. &dev_attr_sticky_key.attr,
  671. &dev_attr_eco_mode.attr,
  672. &dev_attr_ac_brightness.attr,
  673. &dev_attr_dc_brightness.attr,
  674. &dev_attr_current_brightness.attr,
  675. &dev_attr_cdpower.attr,
  676. NULL,
  677. };
  678. static const struct attribute_group pcc_attr_group = {
  679. .name = NULL, /* put in device directory */
  680. .attrs = pcc_sysfs_entries,
  681. };
  682. /* hotkey input device driver */
  683. static int sleep_keydown_seen;
  684. static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
  685. {
  686. struct input_dev *hotk_input_dev = pcc->input_dev;
  687. int rc;
  688. unsigned long long result;
  689. unsigned int key;
  690. unsigned int updown;
  691. rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY,
  692. NULL, &result);
  693. if (ACPI_FAILURE(rc)) {
  694. pr_err("error getting hotkey status\n");
  695. return;
  696. }
  697. key = result & 0xf;
  698. updown = result & 0x80; /* 0x80 == key down; 0x00 = key up */
  699. /* hack: some firmware sends no key down for sleep / hibernate */
  700. if (key == 7 || key == 10) {
  701. if (updown)
  702. sleep_keydown_seen = 1;
  703. if (!sleep_keydown_seen)
  704. sparse_keymap_report_event(hotk_input_dev,
  705. key, 0x80, false);
  706. }
  707. /*
  708. * Don't report brightness key-presses if they are also reported
  709. * by the ACPI video bus.
  710. */
  711. if ((key == 1 || key == 2) && acpi_video_handles_brightness_key_presses())
  712. return;
  713. if (!sparse_keymap_report_event(hotk_input_dev, key, updown, false))
  714. pr_err("Unknown hotkey event: 0x%04llx\n", result);
  715. }
  716. static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event)
  717. {
  718. struct pcc_acpi *pcc = acpi_driver_data(device);
  719. switch (event) {
  720. case HKEY_NOTIFY:
  721. acpi_pcc_generate_keyinput(pcc);
  722. break;
  723. default:
  724. /* nothing to do */
  725. break;
  726. }
  727. }
  728. static void pcc_optd_notify(acpi_handle handle, u32 event, void *data)
  729. {
  730. if (event != ACPI_NOTIFY_EJECT_REQUEST)
  731. return;
  732. set_optd_power_state(0);
  733. }
  734. static int pcc_register_optd_notifier(struct pcc_acpi *pcc, char *node)
  735. {
  736. acpi_status status;
  737. acpi_handle handle;
  738. status = acpi_get_handle(NULL, node, &handle);
  739. if (ACPI_SUCCESS(status)) {
  740. status = acpi_install_notify_handler(handle,
  741. ACPI_SYSTEM_NOTIFY,
  742. pcc_optd_notify, pcc);
  743. if (ACPI_FAILURE(status))
  744. pr_err("Failed to register notify on %s\n", node);
  745. } else
  746. return -ENODEV;
  747. return 0;
  748. }
  749. static void pcc_unregister_optd_notifier(struct pcc_acpi *pcc, char *node)
  750. {
  751. acpi_status status = AE_OK;
  752. acpi_handle handle;
  753. status = acpi_get_handle(NULL, node, &handle);
  754. if (ACPI_SUCCESS(status)) {
  755. status = acpi_remove_notify_handler(handle,
  756. ACPI_SYSTEM_NOTIFY,
  757. pcc_optd_notify);
  758. if (ACPI_FAILURE(status))
  759. pr_err("Error removing optd notify handler %s\n",
  760. node);
  761. }
  762. }
  763. static int acpi_pcc_init_input(struct pcc_acpi *pcc)
  764. {
  765. struct input_dev *input_dev;
  766. int error;
  767. input_dev = input_allocate_device();
  768. if (!input_dev)
  769. return -ENOMEM;
  770. input_dev->name = ACPI_PCC_DRIVER_NAME;
  771. input_dev->phys = ACPI_PCC_INPUT_PHYS;
  772. input_dev->id.bustype = BUS_HOST;
  773. input_dev->id.vendor = 0x0001;
  774. input_dev->id.product = 0x0001;
  775. input_dev->id.version = 0x0100;
  776. error = sparse_keymap_setup(input_dev, panasonic_keymap, NULL);
  777. if (error) {
  778. pr_err("Unable to setup input device keymap\n");
  779. goto err_free_dev;
  780. }
  781. error = input_register_device(input_dev);
  782. if (error) {
  783. pr_err("Unable to register input device\n");
  784. goto err_free_dev;
  785. }
  786. pcc->input_dev = input_dev;
  787. return 0;
  788. err_free_dev:
  789. input_free_device(input_dev);
  790. return error;
  791. }
  792. /* kernel module interface */
  793. #ifdef CONFIG_PM_SLEEP
  794. static int acpi_pcc_hotkey_resume(struct device *dev)
  795. {
  796. struct pcc_acpi *pcc;
  797. if (!dev)
  798. return -EINVAL;
  799. pcc = acpi_driver_data(to_acpi_device(dev));
  800. if (!pcc)
  801. return -EINVAL;
  802. acpi_pcc_write_sset(pcc, SINF_MUTE, pcc->mute);
  803. acpi_pcc_write_sset(pcc, SINF_ECO_MODE, pcc->eco_mode);
  804. acpi_pcc_write_sset(pcc, SINF_STICKY_KEY, pcc->sticky_key);
  805. acpi_pcc_write_sset(pcc, SINF_AC_CUR_BRIGHT, pcc->ac_brightness);
  806. acpi_pcc_write_sset(pcc, SINF_DC_CUR_BRIGHT, pcc->dc_brightness);
  807. acpi_pcc_write_sset(pcc, SINF_CUR_BRIGHT, pcc->current_brightness);
  808. return 0;
  809. }
  810. #endif
  811. static int acpi_pcc_hotkey_add(struct acpi_device *device)
  812. {
  813. struct backlight_properties props;
  814. struct pcc_acpi *pcc;
  815. int num_sifr, result;
  816. if (!device)
  817. return -EINVAL;
  818. num_sifr = acpi_pcc_get_sqty(device);
  819. if (num_sifr < 0 || num_sifr > 255) {
  820. pr_err("num_sifr out of range");
  821. return -ENODEV;
  822. }
  823. pcc = kzalloc(sizeof(struct pcc_acpi), GFP_KERNEL);
  824. if (!pcc) {
  825. pr_err("Couldn't allocate mem for pcc");
  826. return -ENOMEM;
  827. }
  828. pcc->sinf = kcalloc(num_sifr + 1, sizeof(u32), GFP_KERNEL);
  829. if (!pcc->sinf) {
  830. result = -ENOMEM;
  831. goto out_hotkey;
  832. }
  833. pcc->device = device;
  834. pcc->handle = device->handle;
  835. pcc->num_sifr = num_sifr;
  836. device->driver_data = pcc;
  837. strcpy(acpi_device_name(device), ACPI_PCC_DEVICE_NAME);
  838. strcpy(acpi_device_class(device), ACPI_PCC_CLASS);
  839. result = acpi_pcc_init_input(pcc);
  840. if (result) {
  841. pr_err("Error installing keyinput handler\n");
  842. goto out_sinf;
  843. }
  844. if (!acpi_pcc_retrieve_biosdata(pcc)) {
  845. result = -EIO;
  846. pr_err("Couldn't retrieve BIOS data\n");
  847. goto out_input;
  848. }
  849. if (acpi_video_get_backlight_type() == acpi_backlight_vendor) {
  850. /* initialize backlight */
  851. memset(&props, 0, sizeof(struct backlight_properties));
  852. props.type = BACKLIGHT_PLATFORM;
  853. props.max_brightness = pcc->sinf[SINF_AC_MAX_BRIGHT];
  854. pcc->backlight = backlight_device_register("panasonic", NULL, pcc,
  855. &pcc_backlight_ops, &props);
  856. if (IS_ERR(pcc->backlight)) {
  857. result = PTR_ERR(pcc->backlight);
  858. goto out_input;
  859. }
  860. /* read the initial brightness setting from the hardware */
  861. pcc->backlight->props.brightness = pcc->sinf[SINF_AC_CUR_BRIGHT];
  862. }
  863. /* Reset initial sticky key mode since the hardware register state is not consistent */
  864. acpi_pcc_write_sset(pcc, SINF_STICKY_KEY, 0);
  865. pcc->sticky_key = 0;
  866. pcc->eco_mode = pcc->sinf[SINF_ECO_MODE];
  867. pcc->mute = pcc->sinf[SINF_MUTE];
  868. pcc->ac_brightness = pcc->sinf[SINF_AC_CUR_BRIGHT];
  869. pcc->dc_brightness = pcc->sinf[SINF_DC_CUR_BRIGHT];
  870. pcc->current_brightness = pcc->sinf[SINF_CUR_BRIGHT];
  871. /* add sysfs attributes */
  872. result = sysfs_create_group(&device->dev.kobj, &pcc_attr_group);
  873. if (result)
  874. goto out_backlight;
  875. /* optical drive initialization */
  876. if (ACPI_SUCCESS(check_optd_present())) {
  877. pcc->platform = platform_device_register_simple("panasonic",
  878. PLATFORM_DEVID_NONE, NULL, 0);
  879. if (IS_ERR(pcc->platform)) {
  880. result = PTR_ERR(pcc->platform);
  881. goto out_backlight;
  882. }
  883. result = device_create_file(&pcc->platform->dev,
  884. &dev_attr_cdpower);
  885. pcc_register_optd_notifier(pcc, "\\_SB.PCI0.EHCI.ERHB.OPTD");
  886. if (result)
  887. goto out_platform;
  888. } else {
  889. pcc->platform = NULL;
  890. }
  891. i8042_install_filter(panasonic_i8042_filter);
  892. return 0;
  893. out_platform:
  894. platform_device_unregister(pcc->platform);
  895. out_backlight:
  896. backlight_device_unregister(pcc->backlight);
  897. out_input:
  898. input_unregister_device(pcc->input_dev);
  899. out_sinf:
  900. kfree(pcc->sinf);
  901. out_hotkey:
  902. kfree(pcc);
  903. return result;
  904. }
  905. static int acpi_pcc_hotkey_remove(struct acpi_device *device)
  906. {
  907. struct pcc_acpi *pcc = acpi_driver_data(device);
  908. if (!device || !pcc)
  909. return -EINVAL;
  910. i8042_remove_filter(panasonic_i8042_filter);
  911. if (pcc->platform) {
  912. device_remove_file(&pcc->platform->dev, &dev_attr_cdpower);
  913. platform_device_unregister(pcc->platform);
  914. }
  915. pcc_unregister_optd_notifier(pcc, "\\_SB.PCI0.EHCI.ERHB.OPTD");
  916. sysfs_remove_group(&device->dev.kobj, &pcc_attr_group);
  917. backlight_device_unregister(pcc->backlight);
  918. input_unregister_device(pcc->input_dev);
  919. kfree(pcc->sinf);
  920. kfree(pcc);
  921. return 0;
  922. }
  923. module_acpi_driver(acpi_pcc_driver);