lg-laptop.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * lg-laptop.c - LG Gram ACPI features and hotkeys Driver
  4. *
  5. * Copyright (C) 2018 Matan Ziv-Av <matan@svgalib.org>
  6. */
  7. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  8. #include <linux/acpi.h>
  9. #include <linux/bitfield.h>
  10. #include <linux/bits.h>
  11. #include <linux/device.h>
  12. #include <linux/dev_printk.h>
  13. #include <linux/dmi.h>
  14. #include <linux/input.h>
  15. #include <linux/input/sparse-keymap.h>
  16. #include <linux/kernel.h>
  17. #include <linux/leds.h>
  18. #include <linux/module.h>
  19. #include <linux/platform_device.h>
  20. #include <linux/types.h>
  21. #include <acpi/battery.h>
  22. #define LED_DEVICE(_name, max, flag) struct led_classdev _name = { \
  23. .name = __stringify(_name), \
  24. .max_brightness = max, \
  25. .brightness_set = _name##_set, \
  26. .brightness_get = _name##_get, \
  27. .flags = flag, \
  28. }
  29. MODULE_AUTHOR("Matan Ziv-Av");
  30. MODULE_DESCRIPTION("LG WMI Hotkey Driver");
  31. MODULE_LICENSE("GPL");
  32. static bool fw_debug;
  33. module_param(fw_debug, bool, 0);
  34. MODULE_PARM_DESC(fw_debug, "Enable printing of firmware debug messages");
  35. #define LG_ADDRESS_SPACE_ID 0x8F
  36. #define LG_ADDRESS_SPACE_DEBUG_FLAG_ADR 0x00
  37. #define LG_ADDRESS_SPACE_FAN_MODE_ADR 0x03
  38. #define LG_ADDRESS_SPACE_DTTM_FLAG_ADR 0x20
  39. #define LG_ADDRESS_SPACE_CPU_TEMP_ADR 0x21
  40. #define LG_ADDRESS_SPACE_CPU_TRIP_LOW_ADR 0x22
  41. #define LG_ADDRESS_SPACE_CPU_TRIP_HIGH_ADR 0x23
  42. #define LG_ADDRESS_SPACE_MB_TEMP_ADR 0x24
  43. #define LG_ADDRESS_SPACE_MB_TRIP_LOW_ADR 0x25
  44. #define LG_ADDRESS_SPACE_MB_TRIP_HIGH_ADR 0x26
  45. #define LG_ADDRESS_SPACE_DEBUG_MSG_START_ADR 0x3E8
  46. #define LG_ADDRESS_SPACE_DEBUG_MSG_END_ADR 0x5E8
  47. #define WMI_EVENT_GUID0 "E4FB94F9-7F2B-4173-AD1A-CD1D95086248"
  48. #define WMI_EVENT_GUID1 "023B133E-49D1-4E10-B313-698220140DC2"
  49. #define WMI_EVENT_GUID2 "37BE1AC0-C3F2-4B1F-BFBE-8FDEAF2814D6"
  50. #define WMI_EVENT_GUID3 "911BAD44-7DF8-4FBB-9319-BABA1C4B293B"
  51. #define WMI_METHOD_WMAB "C3A72B38-D3EF-42D3-8CBB-D5A57049F66D"
  52. #define WMI_METHOD_WMBB "2B4F501A-BD3C-4394-8DCF-00A7D2BC8210"
  53. #define WMI_EVENT_GUID WMI_EVENT_GUID0
  54. #define SB_GGOV_METHOD "\\_SB.GGOV"
  55. #define GOV_TLED 0x2020008
  56. #define WM_GET 1
  57. #define WM_SET 2
  58. #define WM_KEY_LIGHT 0x400
  59. #define WM_TLED 0x404
  60. #define WM_FN_LOCK 0x407
  61. #define WM_BATT_LIMIT 0x61
  62. #define WM_READER_MODE 0xBF
  63. #define WM_FAN_MODE 0x33
  64. #define WMBB_USB_CHARGE 0x10B
  65. #define WMBB_BATT_LIMIT 0x10C
  66. #define FAN_MODE_LOWER GENMASK(1, 0)
  67. #define FAN_MODE_UPPER GENMASK(5, 4)
  68. #define PLATFORM_NAME "lg-laptop"
  69. MODULE_ALIAS("wmi:" WMI_EVENT_GUID0);
  70. MODULE_ALIAS("wmi:" WMI_EVENT_GUID1);
  71. MODULE_ALIAS("wmi:" WMI_EVENT_GUID2);
  72. MODULE_ALIAS("wmi:" WMI_EVENT_GUID3);
  73. MODULE_ALIAS("wmi:" WMI_METHOD_WMAB);
  74. MODULE_ALIAS("wmi:" WMI_METHOD_WMBB);
  75. static struct platform_device *pf_device;
  76. static struct input_dev *wmi_input_dev;
  77. static u32 inited;
  78. #define INIT_INPUT_WMI_0 0x01
  79. #define INIT_INPUT_WMI_2 0x02
  80. #define INIT_INPUT_ACPI 0x04
  81. #define INIT_SPARSE_KEYMAP 0x80
  82. static int battery_limit_use_wmbb;
  83. static struct led_classdev kbd_backlight;
  84. static enum led_brightness get_kbd_backlight_level(struct device *dev);
  85. static const struct key_entry wmi_keymap[] = {
  86. {KE_KEY, 0x70, {KEY_F15} }, /* LG control panel (F1) */
  87. {KE_KEY, 0x74, {KEY_F21} }, /* Touchpad toggle (F5) */
  88. {KE_KEY, 0xf020000, {KEY_F14} }, /* Read mode (F9) */
  89. {KE_KEY, 0x10000000, {KEY_F16} },/* Keyboard backlight (F8) - pressing
  90. * this key both sends an event and
  91. * changes backlight level.
  92. */
  93. {KE_END, 0}
  94. };
  95. static int ggov(u32 arg0)
  96. {
  97. union acpi_object args[1];
  98. union acpi_object *r;
  99. acpi_status status;
  100. acpi_handle handle;
  101. struct acpi_object_list arg;
  102. struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  103. int res;
  104. args[0].type = ACPI_TYPE_INTEGER;
  105. args[0].integer.value = arg0;
  106. status = acpi_get_handle(NULL, (acpi_string) SB_GGOV_METHOD, &handle);
  107. if (ACPI_FAILURE(status)) {
  108. pr_err("Cannot get handle");
  109. return -ENODEV;
  110. }
  111. arg.count = 1;
  112. arg.pointer = args;
  113. status = acpi_evaluate_object(handle, NULL, &arg, &buffer);
  114. if (ACPI_FAILURE(status)) {
  115. acpi_handle_err(handle, "GGOV: call failed.\n");
  116. return -EINVAL;
  117. }
  118. r = buffer.pointer;
  119. if (r->type != ACPI_TYPE_INTEGER) {
  120. kfree(r);
  121. return -EINVAL;
  122. }
  123. res = r->integer.value;
  124. kfree(r);
  125. return res;
  126. }
  127. static union acpi_object *lg_wmab(struct device *dev, u32 method, u32 arg1, u32 arg2)
  128. {
  129. union acpi_object args[3];
  130. acpi_status status;
  131. struct acpi_object_list arg;
  132. struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  133. args[0].type = ACPI_TYPE_INTEGER;
  134. args[0].integer.value = method;
  135. args[1].type = ACPI_TYPE_INTEGER;
  136. args[1].integer.value = arg1;
  137. args[2].type = ACPI_TYPE_INTEGER;
  138. args[2].integer.value = arg2;
  139. arg.count = 3;
  140. arg.pointer = args;
  141. status = acpi_evaluate_object(ACPI_HANDLE(dev), "WMAB", &arg, &buffer);
  142. if (ACPI_FAILURE(status)) {
  143. dev_err(dev, "WMAB: call failed.\n");
  144. return NULL;
  145. }
  146. return buffer.pointer;
  147. }
  148. static union acpi_object *lg_wmbb(struct device *dev, u32 method_id, u32 arg1, u32 arg2)
  149. {
  150. union acpi_object args[3];
  151. acpi_status status;
  152. struct acpi_object_list arg;
  153. struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  154. u8 buf[32];
  155. *(u32 *)buf = method_id;
  156. *(u32 *)(buf + 4) = arg1;
  157. *(u32 *)(buf + 16) = arg2;
  158. args[0].type = ACPI_TYPE_INTEGER;
  159. args[0].integer.value = 0; /* ignored */
  160. args[1].type = ACPI_TYPE_INTEGER;
  161. args[1].integer.value = 1; /* Must be 1 or 2. Does not matter which */
  162. args[2].type = ACPI_TYPE_BUFFER;
  163. args[2].buffer.length = 32;
  164. args[2].buffer.pointer = buf;
  165. arg.count = 3;
  166. arg.pointer = args;
  167. status = acpi_evaluate_object(ACPI_HANDLE(dev), "WMBB", &arg, &buffer);
  168. if (ACPI_FAILURE(status)) {
  169. dev_err(dev, "WMBB: call failed.\n");
  170. return NULL;
  171. }
  172. return (union acpi_object *)buffer.pointer;
  173. }
  174. static void wmi_notify(union acpi_object *obj, void *context)
  175. {
  176. long data = (long)context;
  177. pr_debug("event guid %li\n", data);
  178. if (!obj)
  179. return;
  180. if (obj->type == ACPI_TYPE_INTEGER) {
  181. int eventcode = obj->integer.value;
  182. struct key_entry *key;
  183. if (eventcode == 0x10000000) {
  184. led_classdev_notify_brightness_hw_changed(
  185. &kbd_backlight, get_kbd_backlight_level(kbd_backlight.dev->parent));
  186. } else {
  187. key = sparse_keymap_entry_from_scancode(
  188. wmi_input_dev, eventcode);
  189. if (key && key->type == KE_KEY)
  190. sparse_keymap_report_entry(wmi_input_dev,
  191. key, 1, true);
  192. }
  193. }
  194. pr_debug("Type: %i Eventcode: 0x%llx\n", obj->type,
  195. obj->integer.value);
  196. }
  197. static void wmi_input_setup(void)
  198. {
  199. acpi_status status;
  200. wmi_input_dev = input_allocate_device();
  201. if (wmi_input_dev) {
  202. wmi_input_dev->name = "LG WMI hotkeys";
  203. wmi_input_dev->phys = "wmi/input0";
  204. wmi_input_dev->id.bustype = BUS_HOST;
  205. if (sparse_keymap_setup(wmi_input_dev, wmi_keymap, NULL) ||
  206. input_register_device(wmi_input_dev)) {
  207. pr_info("Cannot initialize input device");
  208. input_free_device(wmi_input_dev);
  209. return;
  210. }
  211. inited |= INIT_SPARSE_KEYMAP;
  212. status = wmi_install_notify_handler(WMI_EVENT_GUID0, wmi_notify,
  213. (void *)0);
  214. if (ACPI_SUCCESS(status))
  215. inited |= INIT_INPUT_WMI_0;
  216. status = wmi_install_notify_handler(WMI_EVENT_GUID2, wmi_notify,
  217. (void *)2);
  218. if (ACPI_SUCCESS(status))
  219. inited |= INIT_INPUT_WMI_2;
  220. } else {
  221. pr_info("Cannot allocate input device");
  222. }
  223. }
  224. static void acpi_notify(struct acpi_device *device, u32 event)
  225. {
  226. acpi_handle_debug(device->handle, "notify: %d\n", event);
  227. }
  228. static ssize_t fan_mode_store(struct device *dev,
  229. struct device_attribute *attr,
  230. const char *buffer, size_t count)
  231. {
  232. unsigned long value;
  233. union acpi_object *r;
  234. int ret;
  235. ret = kstrtoul(buffer, 10, &value);
  236. if (ret)
  237. return ret;
  238. if (value >= 3)
  239. return -EINVAL;
  240. r = lg_wmab(dev, WM_FAN_MODE, WM_SET,
  241. FIELD_PREP(FAN_MODE_LOWER, value) |
  242. FIELD_PREP(FAN_MODE_UPPER, value));
  243. kfree(r);
  244. return count;
  245. }
  246. static ssize_t fan_mode_show(struct device *dev,
  247. struct device_attribute *attr, char *buffer)
  248. {
  249. unsigned int mode;
  250. union acpi_object *r;
  251. r = lg_wmab(dev, WM_FAN_MODE, WM_GET, 0);
  252. if (!r)
  253. return -EIO;
  254. if (r->type != ACPI_TYPE_INTEGER) {
  255. kfree(r);
  256. return -EIO;
  257. }
  258. mode = FIELD_GET(FAN_MODE_LOWER, r->integer.value);
  259. kfree(r);
  260. return sysfs_emit(buffer, "%d\n", mode);
  261. }
  262. static ssize_t usb_charge_store(struct device *dev,
  263. struct device_attribute *attr,
  264. const char *buffer, size_t count)
  265. {
  266. bool value;
  267. union acpi_object *r;
  268. int ret;
  269. ret = kstrtobool(buffer, &value);
  270. if (ret)
  271. return ret;
  272. r = lg_wmbb(dev, WMBB_USB_CHARGE, WM_SET, value);
  273. if (!r)
  274. return -EIO;
  275. kfree(r);
  276. return count;
  277. }
  278. static ssize_t usb_charge_show(struct device *dev,
  279. struct device_attribute *attr, char *buffer)
  280. {
  281. unsigned int status;
  282. union acpi_object *r;
  283. r = lg_wmbb(dev, WMBB_USB_CHARGE, WM_GET, 0);
  284. if (!r)
  285. return -EIO;
  286. if (r->type != ACPI_TYPE_BUFFER) {
  287. kfree(r);
  288. return -EIO;
  289. }
  290. status = !!r->buffer.pointer[0x10];
  291. kfree(r);
  292. return sysfs_emit(buffer, "%d\n", status);
  293. }
  294. static ssize_t reader_mode_store(struct device *dev,
  295. struct device_attribute *attr,
  296. const char *buffer, size_t count)
  297. {
  298. bool value;
  299. union acpi_object *r;
  300. int ret;
  301. ret = kstrtobool(buffer, &value);
  302. if (ret)
  303. return ret;
  304. r = lg_wmab(dev, WM_READER_MODE, WM_SET, value);
  305. if (!r)
  306. return -EIO;
  307. kfree(r);
  308. return count;
  309. }
  310. static ssize_t reader_mode_show(struct device *dev,
  311. struct device_attribute *attr, char *buffer)
  312. {
  313. unsigned int status;
  314. union acpi_object *r;
  315. r = lg_wmab(dev, WM_READER_MODE, WM_GET, 0);
  316. if (!r)
  317. return -EIO;
  318. if (r->type != ACPI_TYPE_INTEGER) {
  319. kfree(r);
  320. return -EIO;
  321. }
  322. status = !!r->integer.value;
  323. kfree(r);
  324. return sysfs_emit(buffer, "%d\n", status);
  325. }
  326. static ssize_t fn_lock_store(struct device *dev,
  327. struct device_attribute *attr,
  328. const char *buffer, size_t count)
  329. {
  330. bool value;
  331. union acpi_object *r;
  332. int ret;
  333. ret = kstrtobool(buffer, &value);
  334. if (ret)
  335. return ret;
  336. r = lg_wmab(dev, WM_FN_LOCK, WM_SET, value);
  337. if (!r)
  338. return -EIO;
  339. kfree(r);
  340. return count;
  341. }
  342. static ssize_t fn_lock_show(struct device *dev,
  343. struct device_attribute *attr, char *buffer)
  344. {
  345. unsigned int status;
  346. union acpi_object *r;
  347. r = lg_wmab(dev, WM_FN_LOCK, WM_GET, 0);
  348. if (!r)
  349. return -EIO;
  350. if (r->type != ACPI_TYPE_BUFFER) {
  351. kfree(r);
  352. return -EIO;
  353. }
  354. status = !!r->buffer.pointer[0];
  355. kfree(r);
  356. return sysfs_emit(buffer, "%d\n", status);
  357. }
  358. static ssize_t charge_control_end_threshold_store(struct device *dev,
  359. struct device_attribute *attr,
  360. const char *buf, size_t count)
  361. {
  362. unsigned long value;
  363. int ret;
  364. ret = kstrtoul(buf, 10, &value);
  365. if (ret)
  366. return ret;
  367. if (value == 100 || value == 80) {
  368. union acpi_object *r;
  369. if (battery_limit_use_wmbb)
  370. r = lg_wmbb(&pf_device->dev, WMBB_BATT_LIMIT, WM_SET, value);
  371. else
  372. r = lg_wmab(&pf_device->dev, WM_BATT_LIMIT, WM_SET, value);
  373. if (!r)
  374. return -EIO;
  375. kfree(r);
  376. return count;
  377. }
  378. return -EINVAL;
  379. }
  380. static ssize_t charge_control_end_threshold_show(struct device *device,
  381. struct device_attribute *attr,
  382. char *buf)
  383. {
  384. unsigned int status;
  385. union acpi_object *r;
  386. if (battery_limit_use_wmbb) {
  387. r = lg_wmbb(&pf_device->dev, WMBB_BATT_LIMIT, WM_GET, 0);
  388. if (!r)
  389. return -EIO;
  390. if (r->type != ACPI_TYPE_BUFFER) {
  391. kfree(r);
  392. return -EIO;
  393. }
  394. status = r->buffer.pointer[0x10];
  395. } else {
  396. r = lg_wmab(&pf_device->dev, WM_BATT_LIMIT, WM_GET, 0);
  397. if (!r)
  398. return -EIO;
  399. if (r->type != ACPI_TYPE_INTEGER) {
  400. kfree(r);
  401. return -EIO;
  402. }
  403. status = r->integer.value;
  404. }
  405. kfree(r);
  406. if (status != 80 && status != 100)
  407. status = 0;
  408. return sysfs_emit(buf, "%d\n", status);
  409. }
  410. static ssize_t battery_care_limit_show(struct device *dev,
  411. struct device_attribute *attr,
  412. char *buffer)
  413. {
  414. return charge_control_end_threshold_show(dev, attr, buffer);
  415. }
  416. static ssize_t battery_care_limit_store(struct device *dev,
  417. struct device_attribute *attr,
  418. const char *buffer, size_t count)
  419. {
  420. return charge_control_end_threshold_store(dev, attr, buffer, count);
  421. }
  422. static DEVICE_ATTR_RW(fan_mode);
  423. static DEVICE_ATTR_RW(usb_charge);
  424. static DEVICE_ATTR_RW(reader_mode);
  425. static DEVICE_ATTR_RW(fn_lock);
  426. static DEVICE_ATTR_RW(charge_control_end_threshold);
  427. static DEVICE_ATTR_RW(battery_care_limit);
  428. static int lg_battery_add(struct power_supply *battery, struct acpi_battery_hook *hook)
  429. {
  430. if (device_create_file(&battery->dev,
  431. &dev_attr_charge_control_end_threshold))
  432. return -ENODEV;
  433. return 0;
  434. }
  435. static int lg_battery_remove(struct power_supply *battery, struct acpi_battery_hook *hook)
  436. {
  437. device_remove_file(&battery->dev,
  438. &dev_attr_charge_control_end_threshold);
  439. return 0;
  440. }
  441. static struct acpi_battery_hook battery_hook = {
  442. .add_battery = lg_battery_add,
  443. .remove_battery = lg_battery_remove,
  444. .name = "LG Battery Extension",
  445. };
  446. static struct attribute *dev_attributes[] = {
  447. &dev_attr_fan_mode.attr,
  448. &dev_attr_usb_charge.attr,
  449. &dev_attr_reader_mode.attr,
  450. &dev_attr_fn_lock.attr,
  451. &dev_attr_battery_care_limit.attr,
  452. NULL
  453. };
  454. static const struct attribute_group dev_attribute_group = {
  455. .attrs = dev_attributes,
  456. };
  457. static void tpad_led_set(struct led_classdev *cdev,
  458. enum led_brightness brightness)
  459. {
  460. union acpi_object *r;
  461. r = lg_wmab(cdev->dev->parent, WM_TLED, WM_SET, brightness > LED_OFF);
  462. kfree(r);
  463. }
  464. static enum led_brightness tpad_led_get(struct led_classdev *cdev)
  465. {
  466. return ggov(GOV_TLED) > 0 ? LED_ON : LED_OFF;
  467. }
  468. static LED_DEVICE(tpad_led, 1, 0);
  469. static void kbd_backlight_set(struct led_classdev *cdev,
  470. enum led_brightness brightness)
  471. {
  472. u32 val;
  473. union acpi_object *r;
  474. val = 0x22;
  475. if (brightness <= LED_OFF)
  476. val = 0;
  477. if (brightness >= LED_FULL)
  478. val = 0x24;
  479. r = lg_wmab(cdev->dev->parent, WM_KEY_LIGHT, WM_SET, val);
  480. kfree(r);
  481. }
  482. static enum led_brightness get_kbd_backlight_level(struct device *dev)
  483. {
  484. union acpi_object *r;
  485. int val;
  486. r = lg_wmab(dev, WM_KEY_LIGHT, WM_GET, 0);
  487. if (!r)
  488. return LED_OFF;
  489. if (r->type != ACPI_TYPE_BUFFER || r->buffer.pointer[1] != 0x05) {
  490. kfree(r);
  491. return LED_OFF;
  492. }
  493. switch (r->buffer.pointer[0] & 0x27) {
  494. case 0x24:
  495. val = LED_FULL;
  496. break;
  497. case 0x22:
  498. val = LED_HALF;
  499. break;
  500. default:
  501. val = LED_OFF;
  502. }
  503. kfree(r);
  504. return val;
  505. }
  506. static enum led_brightness kbd_backlight_get(struct led_classdev *cdev)
  507. {
  508. return get_kbd_backlight_level(cdev->dev->parent);
  509. }
  510. static LED_DEVICE(kbd_backlight, 255, LED_BRIGHT_HW_CHANGED);
  511. static void wmi_input_destroy(void)
  512. {
  513. if (inited & INIT_INPUT_WMI_2)
  514. wmi_remove_notify_handler(WMI_EVENT_GUID2);
  515. if (inited & INIT_INPUT_WMI_0)
  516. wmi_remove_notify_handler(WMI_EVENT_GUID0);
  517. if (inited & INIT_SPARSE_KEYMAP)
  518. input_unregister_device(wmi_input_dev);
  519. inited &= ~(INIT_INPUT_WMI_0 | INIT_INPUT_WMI_2 | INIT_SPARSE_KEYMAP);
  520. }
  521. static struct platform_driver pf_driver = {
  522. .driver = {
  523. .name = PLATFORM_NAME,
  524. }
  525. };
  526. static acpi_status lg_laptop_address_space_write(struct device *dev, acpi_physical_address address,
  527. size_t size, u64 value)
  528. {
  529. u8 byte;
  530. /* Ignore any debug messages */
  531. if (address >= LG_ADDRESS_SPACE_DEBUG_MSG_START_ADR &&
  532. address <= LG_ADDRESS_SPACE_DEBUG_MSG_END_ADR)
  533. return AE_OK;
  534. if (size != sizeof(byte))
  535. return AE_BAD_PARAMETER;
  536. byte = value & 0xFF;
  537. switch (address) {
  538. case LG_ADDRESS_SPACE_FAN_MODE_ADR:
  539. /*
  540. * The fan mode field is not affected by the DTTM flag, so we
  541. * have to manually check fw_debug.
  542. */
  543. if (fw_debug)
  544. dev_dbg(dev, "Fan mode set to mode %u\n", byte);
  545. return AE_OK;
  546. case LG_ADDRESS_SPACE_CPU_TEMP_ADR:
  547. dev_dbg(dev, "CPU temperature is %u °C\n", byte);
  548. return AE_OK;
  549. case LG_ADDRESS_SPACE_CPU_TRIP_LOW_ADR:
  550. dev_dbg(dev, "CPU lower trip point set to %u °C\n", byte);
  551. return AE_OK;
  552. case LG_ADDRESS_SPACE_CPU_TRIP_HIGH_ADR:
  553. dev_dbg(dev, "CPU higher trip point set to %u °C\n", byte);
  554. return AE_OK;
  555. case LG_ADDRESS_SPACE_MB_TEMP_ADR:
  556. dev_dbg(dev, "Motherboard temperature is %u °C\n", byte);
  557. return AE_OK;
  558. case LG_ADDRESS_SPACE_MB_TRIP_LOW_ADR:
  559. dev_dbg(dev, "Motherboard lower trip point set to %u °C\n", byte);
  560. return AE_OK;
  561. case LG_ADDRESS_SPACE_MB_TRIP_HIGH_ADR:
  562. dev_dbg(dev, "Motherboard higher trip point set to %u °C\n", byte);
  563. return AE_OK;
  564. default:
  565. dev_notice_ratelimited(dev, "Ignoring write to unknown opregion address %llu\n",
  566. address);
  567. return AE_OK;
  568. }
  569. }
  570. static acpi_status lg_laptop_address_space_read(struct device *dev, acpi_physical_address address,
  571. size_t size, u64 *value)
  572. {
  573. if (size != 1)
  574. return AE_BAD_PARAMETER;
  575. switch (address) {
  576. case LG_ADDRESS_SPACE_DEBUG_FLAG_ADR:
  577. /* Debug messages are already printed using the standard ACPI Debug object */
  578. *value = 0x00;
  579. return AE_OK;
  580. case LG_ADDRESS_SPACE_DTTM_FLAG_ADR:
  581. *value = fw_debug;
  582. return AE_OK;
  583. default:
  584. dev_notice_ratelimited(dev, "Attempt to read unknown opregion address %llu\n",
  585. address);
  586. return AE_BAD_PARAMETER;
  587. }
  588. }
  589. static acpi_status lg_laptop_address_space_handler(u32 function, acpi_physical_address address,
  590. u32 bits, u64 *value, void *handler_context,
  591. void *region_context)
  592. {
  593. struct device *dev = handler_context;
  594. size_t size;
  595. if (bits % BITS_PER_BYTE)
  596. return AE_BAD_PARAMETER;
  597. size = bits / BITS_PER_BYTE;
  598. switch (function) {
  599. case ACPI_READ:
  600. return lg_laptop_address_space_read(dev, address, size, value);
  601. case ACPI_WRITE:
  602. return lg_laptop_address_space_write(dev, address, size, *value);
  603. default:
  604. return AE_BAD_PARAMETER;
  605. }
  606. }
  607. static void lg_laptop_remove_address_space_handler(void *data)
  608. {
  609. struct acpi_device *device = data;
  610. acpi_remove_address_space_handler(device->handle, LG_ADDRESS_SPACE_ID,
  611. &lg_laptop_address_space_handler);
  612. }
  613. static int acpi_add(struct acpi_device *device)
  614. {
  615. struct platform_device_info pdev_info = {
  616. .fwnode = acpi_fwnode_handle(device),
  617. .name = PLATFORM_NAME,
  618. .id = PLATFORM_DEVID_NONE,
  619. };
  620. acpi_status status;
  621. int ret;
  622. const char *product;
  623. int year = 2017;
  624. if (pf_device)
  625. return 0;
  626. status = acpi_install_address_space_handler(device->handle, LG_ADDRESS_SPACE_ID,
  627. &lg_laptop_address_space_handler,
  628. NULL, &device->dev);
  629. if (ACPI_FAILURE(status))
  630. return -ENODEV;
  631. ret = devm_add_action_or_reset(&device->dev, lg_laptop_remove_address_space_handler,
  632. device);
  633. if (ret < 0)
  634. return ret;
  635. ret = platform_driver_register(&pf_driver);
  636. if (ret)
  637. return ret;
  638. pf_device = platform_device_register_full(&pdev_info);
  639. if (IS_ERR(pf_device)) {
  640. ret = PTR_ERR(pf_device);
  641. pf_device = NULL;
  642. pr_err("unable to register platform device\n");
  643. goto out_platform_registered;
  644. }
  645. product = dmi_get_system_info(DMI_PRODUCT_NAME);
  646. if (product && strlen(product) > 4)
  647. switch (product[4]) {
  648. case '5':
  649. if (strlen(product) > 5)
  650. switch (product[5]) {
  651. case 'N':
  652. year = 2021;
  653. break;
  654. case '0':
  655. year = 2016;
  656. break;
  657. default:
  658. year = 2022;
  659. }
  660. break;
  661. case '6':
  662. year = 2016;
  663. break;
  664. case '7':
  665. year = 2017;
  666. break;
  667. case '8':
  668. year = 2018;
  669. break;
  670. case '9':
  671. year = 2019;
  672. break;
  673. case '0':
  674. if (strlen(product) > 5)
  675. switch (product[5]) {
  676. case 'N':
  677. year = 2020;
  678. break;
  679. case 'P':
  680. year = 2021;
  681. break;
  682. default:
  683. year = 2022;
  684. }
  685. break;
  686. default:
  687. year = 2019;
  688. }
  689. pr_info("product: %s year: %d\n", product ?: "unknown", year);
  690. if (year >= 2019)
  691. battery_limit_use_wmbb = 1;
  692. ret = sysfs_create_group(&pf_device->dev.kobj, &dev_attribute_group);
  693. if (ret)
  694. goto out_platform_device;
  695. /* LEDs are optional */
  696. led_classdev_register(&pf_device->dev, &kbd_backlight);
  697. led_classdev_register(&pf_device->dev, &tpad_led);
  698. wmi_input_setup();
  699. battery_hook_register(&battery_hook);
  700. return 0;
  701. out_platform_device:
  702. platform_device_unregister(pf_device);
  703. out_platform_registered:
  704. platform_driver_unregister(&pf_driver);
  705. return ret;
  706. }
  707. static void acpi_remove(struct acpi_device *device)
  708. {
  709. sysfs_remove_group(&pf_device->dev.kobj, &dev_attribute_group);
  710. led_classdev_unregister(&tpad_led);
  711. led_classdev_unregister(&kbd_backlight);
  712. battery_hook_unregister(&battery_hook);
  713. wmi_input_destroy();
  714. platform_device_unregister(pf_device);
  715. pf_device = NULL;
  716. platform_driver_unregister(&pf_driver);
  717. }
  718. static const struct acpi_device_id device_ids[] = {
  719. {"LGEX0820", 0},
  720. {"", 0}
  721. };
  722. MODULE_DEVICE_TABLE(acpi, device_ids);
  723. static struct acpi_driver acpi_driver = {
  724. .name = "LG Gram Laptop Support",
  725. .class = "lg-laptop",
  726. .ids = device_ids,
  727. .ops = {
  728. .add = acpi_add,
  729. .remove = acpi_remove,
  730. .notify = acpi_notify,
  731. },
  732. };
  733. static int __init acpi_init(void)
  734. {
  735. int result;
  736. result = acpi_bus_register_driver(&acpi_driver);
  737. if (result < 0) {
  738. pr_debug("Error registering driver\n");
  739. return -ENODEV;
  740. }
  741. return 0;
  742. }
  743. static void __exit acpi_exit(void)
  744. {
  745. acpi_bus_unregister_driver(&acpi_driver);
  746. }
  747. module_init(acpi_init);
  748. module_exit(acpi_exit);