panasonic-laptop.c 29 KB

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