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 return -EIO; 618 } 619 return sysfs_emit(buf, "%u\n", result); 620 } 621 622 static ssize_t eco_mode_store(struct device *dev, struct device_attribute *attr, 623 const char *buf, size_t count) 624 { 625 struct acpi_device *acpi = to_acpi_device(dev); 626 struct pcc_acpi *pcc = acpi_driver_data(acpi); 627 int err, state; 628 629 union acpi_object param[2]; 630 struct acpi_object_list input; 631 acpi_status status; 632 633 param[0].type = ACPI_TYPE_INTEGER; 634 param[0].integer.value = 0x15; 635 param[1].type = ACPI_TYPE_INTEGER; 636 input.count = 2; 637 input.pointer = param; 638 639 err = kstrtoint(buf, 0, &state); 640 if (err) 641 return err; 642 643 switch (state) { 644 case 0: 645 param[1].integer.value = ECO_MODE_OFF; 646 pcc->sinf[SINF_ECO_MODE] = 0; 647 pcc->eco_mode = 0; 648 break; 649 case 1: 650 param[1].integer.value = ECO_MODE_ON; 651 pcc->sinf[SINF_ECO_MODE] = 1; 652 pcc->eco_mode = 1; 653 break; 654 default: 655 /* nothing to do */ 656 return count; 657 } 658 659 status = acpi_evaluate_object(NULL, METHOD_ECWR, 660 &input, NULL); 661 if (ACPI_FAILURE(status)) { 662 pr_err("%s evaluation failed\n", METHOD_ECWR); 663 return -EINVAL; 664 } 665 666 return count; 667 } 668 669 static ssize_t ac_brightness_show(struct device *dev, struct device_attribute *attr, 670 char *buf) 671 { 672 struct acpi_device *acpi = to_acpi_device(dev); 673 struct pcc_acpi *pcc = acpi_driver_data(acpi); 674 675 if (!acpi_pcc_retrieve_biosdata(pcc)) 676 return -EIO; 677 678 return sysfs_emit(buf, "%u\n", pcc->sinf[SINF_AC_CUR_BRIGHT]); 679 } 680 681 static ssize_t ac_brightness_store(struct device *dev, struct device_attribute *attr, 682 const char *buf, size_t count) 683 { 684 struct acpi_device *acpi = to_acpi_device(dev); 685 struct pcc_acpi *pcc = acpi_driver_data(acpi); 686 int err, val; 687 688 err = kstrtoint(buf, 0, &val); 689 if (err) 690 return err; 691 if (val >= 0 && val <= 255) { 692 acpi_pcc_write_sset(pcc, SINF_AC_CUR_BRIGHT, val); 693 pcc->ac_brightness = val; 694 } 695 696 return count; 697 } 698 699 static ssize_t dc_brightness_show(struct device *dev, struct device_attribute *attr, 700 char *buf) 701 { 702 struct acpi_device *acpi = to_acpi_device(dev); 703 struct pcc_acpi *pcc = acpi_driver_data(acpi); 704 705 if (!acpi_pcc_retrieve_biosdata(pcc)) 706 return -EIO; 707 708 return sysfs_emit(buf, "%u\n", pcc->sinf[SINF_DC_CUR_BRIGHT]); 709 } 710 711 static ssize_t dc_brightness_store(struct device *dev, struct device_attribute *attr, 712 const char *buf, size_t count) 713 { 714 struct acpi_device *acpi = to_acpi_device(dev); 715 struct pcc_acpi *pcc = acpi_driver_data(acpi); 716 int err, val; 717 718 err = kstrtoint(buf, 0, &val); 719 if (err) 720 return err; 721 if (val >= 0 && val <= 255) { 722 acpi_pcc_write_sset(pcc, SINF_DC_CUR_BRIGHT, val); 723 pcc->dc_brightness = val; 724 } 725 726 return count; 727 } 728 729 static ssize_t current_brightness_show(struct device *dev, struct device_attribute *attr, 730 char *buf) 731 { 732 struct acpi_device *acpi = to_acpi_device(dev); 733 struct pcc_acpi *pcc = acpi_driver_data(acpi); 734 735 if (!acpi_pcc_retrieve_biosdata(pcc)) 736 return -EIO; 737 738 return sysfs_emit(buf, "%u\n", pcc->sinf[SINF_CUR_BRIGHT]); 739 } 740 741 static ssize_t current_brightness_store(struct device *dev, struct device_attribute *attr, 742 const char *buf, size_t count) 743 { 744 struct acpi_device *acpi = to_acpi_device(dev); 745 struct pcc_acpi *pcc = acpi_driver_data(acpi); 746 int err, val; 747 748 err = kstrtoint(buf, 0, &val); 749 if (err) 750 return err; 751 752 if (val >= 0 && val <= 255) { 753 err = acpi_pcc_write_sset(pcc, SINF_CUR_BRIGHT, val); 754 pcc->current_brightness = val; 755 } 756 757 return count; 758 } 759 760 static ssize_t cdpower_show(struct device *dev, struct device_attribute *attr, 761 char *buf) 762 { 763 int state = get_optd_power_state(); 764 765 if (state < 0) 766 return state; 767 768 return sysfs_emit(buf, "%d\n", state); 769 } 770 771 static ssize_t cdpower_store(struct device *dev, struct device_attribute *attr, 772 const char *buf, size_t count) 773 { 774 int err, val; 775 776 err = kstrtoint(buf, 10, &val); 777 if (err) 778 return err; 779 set_optd_power_state(val); 780 return count; 781 } 782 783 static DEVICE_ATTR_RO(numbatt); 784 static DEVICE_ATTR_RO(lcdtype); 785 static DEVICE_ATTR_RW(mute); 786 static DEVICE_ATTR_RW(sticky_key); 787 static DEVICE_ATTR_RW(eco_mode); 788 static DEVICE_ATTR_RW(ac_brightness); 789 static DEVICE_ATTR_RW(dc_brightness); 790 static DEVICE_ATTR_RW(current_brightness); 791 static DEVICE_ATTR_RW(cdpower); 792 793 static umode_t pcc_sysfs_is_visible(struct kobject *kobj, struct attribute *attr, int idx) 794 { 795 struct device *dev = kobj_to_dev(kobj); 796 struct acpi_device *acpi = to_acpi_device(dev); 797 struct pcc_acpi *pcc = acpi_driver_data(acpi); 798 799 if (attr == &dev_attr_mute.attr) 800 return (pcc->num_sifr > SINF_MUTE) ? attr->mode : 0; 801 802 if (attr == &dev_attr_eco_mode.attr) 803 return (pcc->num_sifr > SINF_ECO_MODE) ? attr->mode : 0; 804 805 if (attr == &dev_attr_current_brightness.attr) 806 return (pcc->num_sifr > SINF_CUR_BRIGHT) ? attr->mode : 0; 807 808 return attr->mode; 809 } 810 811 static struct attribute *pcc_sysfs_entries[] = { 812 &dev_attr_numbatt.attr, 813 &dev_attr_lcdtype.attr, 814 &dev_attr_mute.attr, 815 &dev_attr_sticky_key.attr, 816 &dev_attr_eco_mode.attr, 817 &dev_attr_ac_brightness.attr, 818 &dev_attr_dc_brightness.attr, 819 &dev_attr_current_brightness.attr, 820 &dev_attr_cdpower.attr, 821 NULL, 822 }; 823 824 static const struct attribute_group pcc_attr_group = { 825 .name = NULL, /* put in device directory */ 826 .attrs = pcc_sysfs_entries, 827 .is_visible = pcc_sysfs_is_visible, 828 }; 829 830 831 /* hotkey input device driver */ 832 833 static int sleep_keydown_seen; 834 static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc) 835 { 836 struct input_dev *hotk_input_dev = pcc->input_dev; 837 int rc; 838 unsigned long long result; 839 unsigned int key; 840 unsigned int updown; 841 842 rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY, 843 NULL, &result); 844 if (ACPI_FAILURE(rc)) { 845 pr_err("error getting hotkey status\n"); 846 return; 847 } 848 849 key = result & GENMASK(6, 0); 850 updown = result & BIT(7); /* 0x80 == key down; 0x00 = key up */ 851 852 /* hack: some firmware sends no key down for sleep / hibernate */ 853 if (key == 7 || key == 10) { 854 if (updown) 855 sleep_keydown_seen = 1; 856 if (!sleep_keydown_seen) 857 sparse_keymap_report_event(hotk_input_dev, 858 key, 0x80, false); 859 } 860 861 /* 862 * Don't report brightness key-presses if they are also reported 863 * by the ACPI video bus. 864 */ 865 if ((key == 1 || key == 2) && acpi_video_handles_brightness_key_presses()) 866 return; 867 868 if (!sparse_keymap_report_event(hotk_input_dev, key, updown, false)) 869 pr_err("Unknown hotkey event: 0x%04llx\n", result); 870 } 871 872 static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event) 873 { 874 struct pcc_acpi *pcc = acpi_driver_data(device); 875 876 switch (event) { 877 case HKEY_NOTIFY: 878 acpi_pcc_generate_keyinput(pcc); 879 break; 880 default: 881 /* nothing to do */ 882 break; 883 } 884 } 885 886 static void pcc_optd_notify(acpi_handle handle, u32 event, void *data) 887 { 888 if (event != ACPI_NOTIFY_EJECT_REQUEST) 889 return; 890 891 set_optd_power_state(0); 892 } 893 894 static int pcc_register_optd_notifier(struct pcc_acpi *pcc, char *node) 895 { 896 acpi_status status; 897 acpi_handle handle; 898 899 status = acpi_get_handle(NULL, node, &handle); 900 901 if (ACPI_SUCCESS(status)) { 902 status = acpi_install_notify_handler(handle, 903 ACPI_SYSTEM_NOTIFY, 904 pcc_optd_notify, pcc); 905 if (ACPI_FAILURE(status)) 906 pr_err("Failed to register notify on %s\n", node); 907 } else 908 return -ENODEV; 909 910 return 0; 911 } 912 913 static void pcc_unregister_optd_notifier(struct pcc_acpi *pcc, char *node) 914 { 915 acpi_status status = AE_OK; 916 acpi_handle handle; 917 918 status = acpi_get_handle(NULL, node, &handle); 919 920 if (ACPI_SUCCESS(status)) { 921 status = acpi_remove_notify_handler(handle, 922 ACPI_SYSTEM_NOTIFY, 923 pcc_optd_notify); 924 if (ACPI_FAILURE(status)) 925 pr_err("Error removing optd notify handler %s\n", 926 node); 927 } 928 } 929 930 static int acpi_pcc_init_input(struct pcc_acpi *pcc) 931 { 932 struct input_dev *input_dev; 933 int error; 934 935 input_dev = input_allocate_device(); 936 if (!input_dev) 937 return -ENOMEM; 938 939 input_dev->name = ACPI_PCC_DRIVER_NAME; 940 input_dev->phys = ACPI_PCC_INPUT_PHYS; 941 input_dev->id.bustype = BUS_HOST; 942 input_dev->id.vendor = 0x0001; 943 input_dev->id.product = 0x0001; 944 input_dev->id.version = 0x0100; 945 946 error = sparse_keymap_setup(input_dev, panasonic_keymap, NULL); 947 if (error) { 948 pr_err("Unable to setup input device keymap\n"); 949 goto err_free_dev; 950 } 951 952 error = input_register_device(input_dev); 953 if (error) { 954 pr_err("Unable to register input device\n"); 955 goto err_free_dev; 956 } 957 958 pcc->input_dev = input_dev; 959 return 0; 960 961 err_free_dev: 962 input_free_device(input_dev); 963 return error; 964 } 965 966 /* kernel module interface */ 967 968 #ifdef CONFIG_PM_SLEEP 969 static int acpi_pcc_hotkey_resume(struct device *dev) 970 { 971 struct pcc_acpi *pcc; 972 973 if (!dev) 974 return -EINVAL; 975 976 pcc = acpi_driver_data(to_acpi_device(dev)); 977 if (!pcc) 978 return -EINVAL; 979 980 if (pcc->num_sifr > SINF_MUTE) 981 acpi_pcc_write_sset(pcc, SINF_MUTE, pcc->mute); 982 if (pcc->num_sifr > SINF_ECO_MODE) 983 acpi_pcc_write_sset(pcc, SINF_ECO_MODE, pcc->eco_mode); 984 acpi_pcc_write_sset(pcc, SINF_STICKY_KEY, pcc->sticky_key); 985 acpi_pcc_write_sset(pcc, SINF_AC_CUR_BRIGHT, pcc->ac_brightness); 986 acpi_pcc_write_sset(pcc, SINF_DC_CUR_BRIGHT, pcc->dc_brightness); 987 if (pcc->num_sifr > SINF_CUR_BRIGHT) 988 acpi_pcc_write_sset(pcc, SINF_CUR_BRIGHT, pcc->current_brightness); 989 990 return 0; 991 } 992 #endif 993 994 static int acpi_pcc_hotkey_add(struct acpi_device *device) 995 { 996 struct backlight_properties props; 997 struct pcc_acpi *pcc; 998 int num_sifr, result; 999 1000 if (!device) 1001 return -EINVAL; 1002 1003 num_sifr = acpi_pcc_get_sqty(device); 1004 1005 /* 1006 * pcc->sinf is expected to at least have the AC+DC brightness entries. 1007 * Accesses to higher SINF entries are checked against num_sifr. 1008 */ 1009 if (num_sifr <= SINF_DC_CUR_BRIGHT || num_sifr > 255) { 1010 pr_err("num_sifr %d out of range %d - 255\n", num_sifr, SINF_DC_CUR_BRIGHT + 1); 1011 return -ENODEV; 1012 } 1013 1014 /* 1015 * Some DSDT-s have an off-by-one bug where the SINF package count is 1016 * one higher than the SQTY reported value, allocate 1 entry extra. 1017 */ 1018 num_sifr++; 1019 1020 pcc = kzalloc(sizeof(struct pcc_acpi), GFP_KERNEL); 1021 if (!pcc) { 1022 pr_err("Couldn't allocate mem for pcc"); 1023 return -ENOMEM; 1024 } 1025 1026 pcc->sinf = kcalloc(num_sifr + 1, sizeof(u32), GFP_KERNEL); 1027 if (!pcc->sinf) { 1028 result = -ENOMEM; 1029 goto out_hotkey; 1030 } 1031 1032 pcc->device = device; 1033 pcc->handle = device->handle; 1034 pcc->num_sifr = num_sifr; 1035 device->driver_data = pcc; 1036 strcpy(acpi_device_name(device), ACPI_PCC_DEVICE_NAME); 1037 strcpy(acpi_device_class(device), ACPI_PCC_CLASS); 1038 1039 result = acpi_pcc_init_input(pcc); 1040 if (result) { 1041 pr_err("Error installing keyinput handler\n"); 1042 goto out_sinf; 1043 } 1044 1045 if (!acpi_pcc_retrieve_biosdata(pcc)) { 1046 result = -EIO; 1047 pr_err("Couldn't retrieve BIOS data\n"); 1048 goto out_input; 1049 } 1050 1051 if (acpi_video_get_backlight_type() == acpi_backlight_vendor) { 1052 /* initialize backlight */ 1053 memset(&props, 0, sizeof(struct backlight_properties)); 1054 props.type = BACKLIGHT_PLATFORM; 1055 props.max_brightness = pcc->sinf[SINF_AC_MAX_BRIGHT]; 1056 1057 pcc->backlight = backlight_device_register("panasonic", NULL, pcc, 1058 &pcc_backlight_ops, &props); 1059 if (IS_ERR(pcc->backlight)) { 1060 result = PTR_ERR(pcc->backlight); 1061 goto out_input; 1062 } 1063 1064 /* read the initial brightness setting from the hardware */ 1065 pcc->backlight->props.brightness = pcc->sinf[SINF_AC_CUR_BRIGHT]; 1066 } 1067 1068 /* Reset initial sticky key mode since the hardware register state is not consistent */ 1069 acpi_pcc_write_sset(pcc, SINF_STICKY_KEY, 0); 1070 pcc->sticky_key = 0; 1071 1072 pcc->ac_brightness = pcc->sinf[SINF_AC_CUR_BRIGHT]; 1073 pcc->dc_brightness = pcc->sinf[SINF_DC_CUR_BRIGHT]; 1074 if (pcc->num_sifr > SINF_MUTE) 1075 pcc->mute = pcc->sinf[SINF_MUTE]; 1076 if (pcc->num_sifr > SINF_ECO_MODE) 1077 pcc->eco_mode = pcc->sinf[SINF_ECO_MODE]; 1078 if (pcc->num_sifr > SINF_CUR_BRIGHT) 1079 pcc->current_brightness = pcc->sinf[SINF_CUR_BRIGHT]; 1080 1081 /* add sysfs attributes */ 1082 result = sysfs_create_group(&device->dev.kobj, &pcc_attr_group); 1083 if (result) 1084 goto out_backlight; 1085 1086 /* optical drive initialization */ 1087 if (ACPI_SUCCESS(check_optd_present())) { 1088 pcc->platform = platform_device_register_simple("panasonic", 1089 PLATFORM_DEVID_NONE, NULL, 0); 1090 if (IS_ERR(pcc->platform)) { 1091 result = PTR_ERR(pcc->platform); 1092 goto out_backlight; 1093 } 1094 result = device_create_file(&pcc->platform->dev, 1095 &dev_attr_cdpower); 1096 pcc_register_optd_notifier(pcc, "\\_SB.PCI0.EHCI.ERHB.OPTD"); 1097 if (result) 1098 goto out_platform; 1099 } else { 1100 pcc->platform = NULL; 1101 } 1102 1103 i8042_install_filter(panasonic_i8042_filter); 1104 return 0; 1105 1106 out_platform: 1107 platform_device_unregister(pcc->platform); 1108 out_backlight: 1109 backlight_device_unregister(pcc->backlight); 1110 out_input: 1111 input_unregister_device(pcc->input_dev); 1112 out_sinf: 1113 kfree(pcc->sinf); 1114 out_hotkey: 1115 kfree(pcc); 1116 1117 return result; 1118 } 1119 1120 static void acpi_pcc_hotkey_remove(struct acpi_device *device) 1121 { 1122 struct pcc_acpi *pcc = acpi_driver_data(device); 1123 1124 if (!device || !pcc) 1125 return; 1126 1127 i8042_remove_filter(panasonic_i8042_filter); 1128 1129 if (pcc->platform) { 1130 device_remove_file(&pcc->platform->dev, &dev_attr_cdpower); 1131 platform_device_unregister(pcc->platform); 1132 } 1133 pcc_unregister_optd_notifier(pcc, "\\_SB.PCI0.EHCI.ERHB.OPTD"); 1134 1135 sysfs_remove_group(&device->dev.kobj, &pcc_attr_group); 1136 1137 backlight_device_unregister(pcc->backlight); 1138 1139 input_unregister_device(pcc->input_dev); 1140 1141 kfree(pcc->sinf); 1142 kfree(pcc); 1143 } 1144 1145 module_acpi_driver(acpi_pcc_driver); 1146