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