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