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