0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122 #include <linux/acpi.h>
0123 #include <linux/backlight.h>
0124 #include <linux/ctype.h>
0125 #include <linux/i8042.h>
0126 #include <linux/init.h>
0127 #include <linux/input.h>
0128 #include <linux/input/sparse-keymap.h>
0129 #include <linux/kernel.h>
0130 #include <linux/module.h>
0131 #include <linux/platform_device.h>
0132 #include <linux/seq_file.h>
0133 #include <linux/serio.h>
0134 #include <linux/slab.h>
0135 #include <linux/types.h>
0136 #include <linux/uaccess.h>
0137 #include <acpi/video.h>
0138
0139 MODULE_AUTHOR("Hiroshi Miura <miura@da-cha.org>");
0140 MODULE_AUTHOR("David Bronaugh <dbronaugh@linuxboxen.org>");
0141 MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
0142 MODULE_AUTHOR("Martin Lucina <mato@kotelna.sk>");
0143 MODULE_AUTHOR("Kenneth Chan <kenneth.t.chan@gmail.com>");
0144 MODULE_DESCRIPTION("ACPI HotKey driver for Panasonic Let's Note laptops");
0145 MODULE_LICENSE("GPL");
0146
0147 #define LOGPREFIX "pcc_acpi: "
0148
0149
0150
0151 #define METHOD_HKEY_QUERY "HINF"
0152 #define METHOD_HKEY_SQTY "SQTY"
0153 #define METHOD_HKEY_SINF "SINF"
0154 #define METHOD_HKEY_SSET "SSET"
0155 #define METHOD_ECWR "\\_SB.ECWR"
0156 #define HKEY_NOTIFY 0x80
0157 #define ECO_MODE_OFF 0x00
0158 #define ECO_MODE_ON 0x80
0159
0160 #define ACPI_PCC_DRIVER_NAME "Panasonic Laptop Support"
0161 #define ACPI_PCC_DEVICE_NAME "Hotkey"
0162 #define ACPI_PCC_CLASS "pcc"
0163
0164 #define ACPI_PCC_INPUT_PHYS "panasonic/hkey0"
0165
0166
0167
0168
0169 enum SINF_BITS { SINF_NUM_BATTERIES = 0,
0170 SINF_LCD_TYPE,
0171 SINF_AC_MAX_BRIGHT,
0172 SINF_AC_MIN_BRIGHT,
0173 SINF_AC_CUR_BRIGHT,
0174 SINF_DC_MAX_BRIGHT,
0175 SINF_DC_MIN_BRIGHT,
0176 SINF_DC_CUR_BRIGHT,
0177 SINF_MUTE,
0178 SINF_RESERVED,
0179 SINF_ECO_MODE = 0x0A,
0180 SINF_CUR_BRIGHT = 0x0D,
0181 SINF_STICKY_KEY = 0x80,
0182 };
0183
0184
0185 static int acpi_pcc_hotkey_add(struct acpi_device *device);
0186 static int acpi_pcc_hotkey_remove(struct acpi_device *device);
0187 static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event);
0188
0189 static const struct acpi_device_id pcc_device_ids[] = {
0190 { "MAT0012", 0},
0191 { "MAT0013", 0},
0192 { "MAT0018", 0},
0193 { "MAT0019", 0},
0194 { "", 0},
0195 };
0196 MODULE_DEVICE_TABLE(acpi, pcc_device_ids);
0197
0198 #ifdef CONFIG_PM_SLEEP
0199 static int acpi_pcc_hotkey_resume(struct device *dev);
0200 #endif
0201 static SIMPLE_DEV_PM_OPS(acpi_pcc_hotkey_pm, NULL, acpi_pcc_hotkey_resume);
0202
0203 static struct acpi_driver acpi_pcc_driver = {
0204 .name = ACPI_PCC_DRIVER_NAME,
0205 .class = ACPI_PCC_CLASS,
0206 .ids = pcc_device_ids,
0207 .ops = {
0208 .add = acpi_pcc_hotkey_add,
0209 .remove = acpi_pcc_hotkey_remove,
0210 .notify = acpi_pcc_hotkey_notify,
0211 },
0212 .drv.pm = &acpi_pcc_hotkey_pm,
0213 };
0214
0215 static const struct key_entry panasonic_keymap[] = {
0216 { KE_KEY, 0, { KEY_RESERVED } },
0217 { KE_KEY, 1, { KEY_BRIGHTNESSDOWN } },
0218 { KE_KEY, 2, { KEY_BRIGHTNESSUP } },
0219 { KE_KEY, 3, { KEY_DISPLAYTOGGLE } },
0220 { KE_KEY, 4, { KEY_MUTE } },
0221 { KE_KEY, 5, { KEY_VOLUMEDOWN } },
0222 { KE_KEY, 6, { KEY_VOLUMEUP } },
0223 { KE_KEY, 7, { KEY_SLEEP } },
0224 { KE_KEY, 8, { KEY_PROG1 } },
0225 { KE_KEY, 9, { KEY_BATTERY } },
0226 { KE_KEY, 10, { KEY_SUSPEND } },
0227 { KE_END, 0 }
0228 };
0229
0230 struct pcc_acpi {
0231 acpi_handle handle;
0232 unsigned long num_sifr;
0233 int sticky_key;
0234 int eco_mode;
0235 int mute;
0236 int ac_brightness;
0237 int dc_brightness;
0238 int current_brightness;
0239 u32 *sinf;
0240 struct acpi_device *device;
0241 struct input_dev *input_dev;
0242 struct backlight_device *backlight;
0243 struct platform_device *platform;
0244 };
0245
0246
0247
0248
0249
0250 static bool panasonic_i8042_filter(unsigned char data, unsigned char str,
0251 struct serio *port)
0252 {
0253 static bool extended;
0254
0255 if (str & I8042_STR_AUXDATA)
0256 return false;
0257
0258 if (data == 0xe0) {
0259 extended = true;
0260 return true;
0261 } else if (extended) {
0262 extended = false;
0263
0264 switch (data & 0x7f) {
0265 case 0x20:
0266 case 0x2e:
0267 case 0x30:
0268 return true;
0269 default:
0270
0271
0272
0273
0274 serio_interrupt(port, 0xe0, 0);
0275 return false;
0276 }
0277 }
0278
0279 return false;
0280 }
0281
0282
0283 static int acpi_pcc_write_sset(struct pcc_acpi *pcc, int func, int val)
0284 {
0285 union acpi_object in_objs[] = {
0286 { .integer.type = ACPI_TYPE_INTEGER,
0287 .integer.value = func, },
0288 { .integer.type = ACPI_TYPE_INTEGER,
0289 .integer.value = val, },
0290 };
0291 struct acpi_object_list params = {
0292 .count = ARRAY_SIZE(in_objs),
0293 .pointer = in_objs,
0294 };
0295 acpi_status status = AE_OK;
0296
0297 status = acpi_evaluate_object(pcc->handle, METHOD_HKEY_SSET,
0298 ¶ms, NULL);
0299
0300 return (status == AE_OK) ? 0 : -EIO;
0301 }
0302
0303 static inline int acpi_pcc_get_sqty(struct acpi_device *device)
0304 {
0305 unsigned long long s;
0306 acpi_status status;
0307
0308 status = acpi_evaluate_integer(device->handle, METHOD_HKEY_SQTY,
0309 NULL, &s);
0310 if (ACPI_SUCCESS(status))
0311 return s;
0312 else {
0313 pr_err("evaluation error HKEY.SQTY\n");
0314 return -EINVAL;
0315 }
0316 }
0317
0318 static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc)
0319 {
0320 acpi_status status;
0321 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
0322 union acpi_object *hkey = NULL;
0323 int i;
0324
0325 status = acpi_evaluate_object(pcc->handle, METHOD_HKEY_SINF, NULL,
0326 &buffer);
0327 if (ACPI_FAILURE(status)) {
0328 pr_err("evaluation error HKEY.SINF\n");
0329 return 0;
0330 }
0331
0332 hkey = buffer.pointer;
0333 if (!hkey || (hkey->type != ACPI_TYPE_PACKAGE)) {
0334 pr_err("Invalid HKEY.SINF\n");
0335 status = AE_ERROR;
0336 goto end;
0337 }
0338
0339 if (pcc->num_sifr < hkey->package.count) {
0340 pr_err("SQTY reports bad SINF length\n");
0341 status = AE_ERROR;
0342 goto end;
0343 }
0344
0345 for (i = 0; i < hkey->package.count; i++) {
0346 union acpi_object *element = &(hkey->package.elements[i]);
0347 if (likely(element->type == ACPI_TYPE_INTEGER)) {
0348 pcc->sinf[i] = element->integer.value;
0349 } else
0350 pr_err("Invalid HKEY.SINF data\n");
0351 }
0352 pcc->sinf[hkey->package.count] = -1;
0353
0354 end:
0355 kfree(buffer.pointer);
0356 return status == AE_OK;
0357 }
0358
0359
0360
0361
0362
0363
0364
0365
0366 static int bl_get(struct backlight_device *bd)
0367 {
0368 struct pcc_acpi *pcc = bl_get_data(bd);
0369
0370 if (!acpi_pcc_retrieve_biosdata(pcc))
0371 return -EIO;
0372
0373 return pcc->sinf[SINF_AC_CUR_BRIGHT];
0374 }
0375
0376 static int bl_set_status(struct backlight_device *bd)
0377 {
0378 struct pcc_acpi *pcc = bl_get_data(bd);
0379 int bright = bd->props.brightness;
0380 int rc;
0381
0382 if (!acpi_pcc_retrieve_biosdata(pcc))
0383 return -EIO;
0384
0385 if (bright < pcc->sinf[SINF_AC_MIN_BRIGHT])
0386 bright = pcc->sinf[SINF_AC_MIN_BRIGHT];
0387
0388 if (bright < pcc->sinf[SINF_DC_MIN_BRIGHT])
0389 bright = pcc->sinf[SINF_DC_MIN_BRIGHT];
0390
0391 if (bright < pcc->sinf[SINF_AC_MIN_BRIGHT] ||
0392 bright > pcc->sinf[SINF_AC_MAX_BRIGHT])
0393 return -EINVAL;
0394
0395 rc = acpi_pcc_write_sset(pcc, SINF_AC_CUR_BRIGHT, bright);
0396 if (rc < 0)
0397 return rc;
0398
0399 return acpi_pcc_write_sset(pcc, SINF_DC_CUR_BRIGHT, bright);
0400 }
0401
0402 static const struct backlight_ops pcc_backlight_ops = {
0403 .get_brightness = bl_get,
0404 .update_status = bl_set_status,
0405 };
0406
0407
0408
0409
0410 static acpi_status check_optd_present(void)
0411 {
0412 acpi_status status = AE_OK;
0413 acpi_handle handle;
0414
0415 status = acpi_get_handle(NULL, "\\_SB.STAT", &handle);
0416 if (ACPI_FAILURE(status))
0417 goto out;
0418 status = acpi_get_handle(NULL, "\\_SB.FBAY", &handle);
0419 if (ACPI_FAILURE(status))
0420 goto out;
0421 status = acpi_get_handle(NULL, "\\_SB.CDDI", &handle);
0422 if (ACPI_FAILURE(status))
0423 goto out;
0424
0425 out:
0426 return status;
0427 }
0428
0429
0430
0431 static int get_optd_power_state(void)
0432 {
0433 acpi_status status;
0434 unsigned long long state;
0435 int result;
0436
0437 status = acpi_evaluate_integer(NULL, "\\_SB.STAT", NULL, &state);
0438 if (ACPI_FAILURE(status)) {
0439 pr_err("evaluation error _SB.STAT\n");
0440 result = -EIO;
0441 goto out;
0442 }
0443 switch (state) {
0444 case 0:
0445 result = 0;
0446 break;
0447 case 0x0f:
0448 result = 1;
0449 break;
0450 default:
0451 result = -EIO;
0452 break;
0453 }
0454
0455 out:
0456 return result;
0457 }
0458
0459
0460
0461 static int set_optd_power_state(int new_state)
0462 {
0463 int result;
0464 acpi_status status;
0465
0466 result = get_optd_power_state();
0467 if (result < 0)
0468 goto out;
0469 if (new_state == result)
0470 goto out;
0471
0472 switch (new_state) {
0473 case 0:
0474
0475
0476
0477 status = acpi_evaluate_object(NULL, "\\_SB.CDDR", NULL, NULL);
0478 if (ACPI_FAILURE(status)) {
0479 pr_err("evaluation error _SB.CDDR\n");
0480 result = -EIO;
0481 }
0482 break;
0483 case 1:
0484 status = acpi_evaluate_object(NULL, "\\_SB.FBAY", NULL, NULL);
0485 if (ACPI_FAILURE(status)) {
0486 pr_err("evaluation error _SB.FBAY\n");
0487 result = -EIO;
0488 }
0489 break;
0490 default:
0491 result = -EINVAL;
0492 break;
0493 }
0494
0495 out:
0496 return result;
0497 }
0498
0499
0500
0501
0502 static ssize_t numbatt_show(struct device *dev, struct device_attribute *attr,
0503 char *buf)
0504 {
0505 struct acpi_device *acpi = to_acpi_device(dev);
0506 struct pcc_acpi *pcc = acpi_driver_data(acpi);
0507
0508 if (!acpi_pcc_retrieve_biosdata(pcc))
0509 return -EIO;
0510
0511 return sysfs_emit(buf, "%u\n", pcc->sinf[SINF_NUM_BATTERIES]);
0512 }
0513
0514 static ssize_t lcdtype_show(struct device *dev, struct device_attribute *attr,
0515 char *buf)
0516 {
0517 struct acpi_device *acpi = to_acpi_device(dev);
0518 struct pcc_acpi *pcc = acpi_driver_data(acpi);
0519
0520 if (!acpi_pcc_retrieve_biosdata(pcc))
0521 return -EIO;
0522
0523 return sysfs_emit(buf, "%u\n", pcc->sinf[SINF_LCD_TYPE]);
0524 }
0525
0526 static ssize_t mute_show(struct device *dev, struct device_attribute *attr,
0527 char *buf)
0528 {
0529 struct acpi_device *acpi = to_acpi_device(dev);
0530 struct pcc_acpi *pcc = acpi_driver_data(acpi);
0531
0532 if (!acpi_pcc_retrieve_biosdata(pcc))
0533 return -EIO;
0534
0535 return sysfs_emit(buf, "%u\n", pcc->sinf[SINF_MUTE]);
0536 }
0537
0538 static ssize_t mute_store(struct device *dev, struct device_attribute *attr,
0539 const char *buf, size_t count)
0540 {
0541 struct acpi_device *acpi = to_acpi_device(dev);
0542 struct pcc_acpi *pcc = acpi_driver_data(acpi);
0543 int err, val;
0544
0545 err = kstrtoint(buf, 0, &val);
0546 if (err)
0547 return err;
0548 if (val == 0 || val == 1) {
0549 acpi_pcc_write_sset(pcc, SINF_MUTE, val);
0550 pcc->mute = val;
0551 }
0552
0553 return count;
0554 }
0555
0556 static ssize_t sticky_key_show(struct device *dev, struct device_attribute *attr,
0557 char *buf)
0558 {
0559 struct acpi_device *acpi = to_acpi_device(dev);
0560 struct pcc_acpi *pcc = acpi_driver_data(acpi);
0561
0562 if (!acpi_pcc_retrieve_biosdata(pcc))
0563 return -EIO;
0564
0565 return sysfs_emit(buf, "%u\n", pcc->sticky_key);
0566 }
0567
0568 static ssize_t sticky_key_store(struct device *dev, struct device_attribute *attr,
0569 const char *buf, size_t count)
0570 {
0571 struct acpi_device *acpi = to_acpi_device(dev);
0572 struct pcc_acpi *pcc = acpi_driver_data(acpi);
0573 int err, val;
0574
0575 err = kstrtoint(buf, 0, &val);
0576 if (err)
0577 return err;
0578 if (val == 0 || val == 1) {
0579 acpi_pcc_write_sset(pcc, SINF_STICKY_KEY, val);
0580 pcc->sticky_key = val;
0581 }
0582
0583 return count;
0584 }
0585
0586 static ssize_t eco_mode_show(struct device *dev, struct device_attribute *attr,
0587 char *buf)
0588 {
0589 struct acpi_device *acpi = to_acpi_device(dev);
0590 struct pcc_acpi *pcc = acpi_driver_data(acpi);
0591 int result;
0592
0593 if (!acpi_pcc_retrieve_biosdata(pcc))
0594 return -EIO;
0595
0596 switch (pcc->sinf[SINF_ECO_MODE]) {
0597 case (ECO_MODE_OFF + 3):
0598 result = 0;
0599 break;
0600 case (ECO_MODE_ON + 3):
0601 result = 1;
0602 break;
0603 default:
0604 result = -EIO;
0605 break;
0606 }
0607 return sysfs_emit(buf, "%u\n", result);
0608 }
0609
0610 static ssize_t eco_mode_store(struct device *dev, struct device_attribute *attr,
0611 const char *buf, size_t count)
0612 {
0613 struct acpi_device *acpi = to_acpi_device(dev);
0614 struct pcc_acpi *pcc = acpi_driver_data(acpi);
0615 int err, state;
0616
0617 union acpi_object param[2];
0618 struct acpi_object_list input;
0619 acpi_status status;
0620
0621 param[0].type = ACPI_TYPE_INTEGER;
0622 param[0].integer.value = 0x15;
0623 param[1].type = ACPI_TYPE_INTEGER;
0624 input.count = 2;
0625 input.pointer = param;
0626
0627 err = kstrtoint(buf, 0, &state);
0628 if (err)
0629 return err;
0630
0631 switch (state) {
0632 case 0:
0633 param[1].integer.value = ECO_MODE_OFF;
0634 pcc->sinf[SINF_ECO_MODE] = 0;
0635 pcc->eco_mode = 0;
0636 break;
0637 case 1:
0638 param[1].integer.value = ECO_MODE_ON;
0639 pcc->sinf[SINF_ECO_MODE] = 1;
0640 pcc->eco_mode = 1;
0641 break;
0642 default:
0643
0644 return count;
0645 }
0646
0647 status = acpi_evaluate_object(NULL, METHOD_ECWR,
0648 &input, NULL);
0649 if (ACPI_FAILURE(status)) {
0650 pr_err("%s evaluation failed\n", METHOD_ECWR);
0651 return -EINVAL;
0652 }
0653
0654 return count;
0655 }
0656
0657 static ssize_t ac_brightness_show(struct device *dev, struct device_attribute *attr,
0658 char *buf)
0659 {
0660 struct acpi_device *acpi = to_acpi_device(dev);
0661 struct pcc_acpi *pcc = acpi_driver_data(acpi);
0662
0663 if (!acpi_pcc_retrieve_biosdata(pcc))
0664 return -EIO;
0665
0666 return sysfs_emit(buf, "%u\n", pcc->sinf[SINF_AC_CUR_BRIGHT]);
0667 }
0668
0669 static ssize_t ac_brightness_store(struct device *dev, struct device_attribute *attr,
0670 const char *buf, size_t count)
0671 {
0672 struct acpi_device *acpi = to_acpi_device(dev);
0673 struct pcc_acpi *pcc = acpi_driver_data(acpi);
0674 int err, val;
0675
0676 err = kstrtoint(buf, 0, &val);
0677 if (err)
0678 return err;
0679 if (val >= 0 && val <= 255) {
0680 acpi_pcc_write_sset(pcc, SINF_AC_CUR_BRIGHT, val);
0681 pcc->ac_brightness = val;
0682 }
0683
0684 return count;
0685 }
0686
0687 static ssize_t dc_brightness_show(struct device *dev, struct device_attribute *attr,
0688 char *buf)
0689 {
0690 struct acpi_device *acpi = to_acpi_device(dev);
0691 struct pcc_acpi *pcc = acpi_driver_data(acpi);
0692
0693 if (!acpi_pcc_retrieve_biosdata(pcc))
0694 return -EIO;
0695
0696 return sysfs_emit(buf, "%u\n", pcc->sinf[SINF_DC_CUR_BRIGHT]);
0697 }
0698
0699 static ssize_t dc_brightness_store(struct device *dev, struct device_attribute *attr,
0700 const char *buf, size_t count)
0701 {
0702 struct acpi_device *acpi = to_acpi_device(dev);
0703 struct pcc_acpi *pcc = acpi_driver_data(acpi);
0704 int err, val;
0705
0706 err = kstrtoint(buf, 0, &val);
0707 if (err)
0708 return err;
0709 if (val >= 0 && val <= 255) {
0710 acpi_pcc_write_sset(pcc, SINF_DC_CUR_BRIGHT, val);
0711 pcc->dc_brightness = val;
0712 }
0713
0714 return count;
0715 }
0716
0717 static ssize_t current_brightness_show(struct device *dev, struct device_attribute *attr,
0718 char *buf)
0719 {
0720 struct acpi_device *acpi = to_acpi_device(dev);
0721 struct pcc_acpi *pcc = acpi_driver_data(acpi);
0722
0723 if (!acpi_pcc_retrieve_biosdata(pcc))
0724 return -EIO;
0725
0726 return sysfs_emit(buf, "%u\n", pcc->sinf[SINF_CUR_BRIGHT]);
0727 }
0728
0729 static ssize_t current_brightness_store(struct device *dev, struct device_attribute *attr,
0730 const char *buf, size_t count)
0731 {
0732 struct acpi_device *acpi = to_acpi_device(dev);
0733 struct pcc_acpi *pcc = acpi_driver_data(acpi);
0734 int err, val;
0735
0736 err = kstrtoint(buf, 0, &val);
0737 if (err)
0738 return err;
0739
0740 if (val >= 0 && val <= 255) {
0741 err = acpi_pcc_write_sset(pcc, SINF_CUR_BRIGHT, val);
0742 pcc->current_brightness = val;
0743 }
0744
0745 return count;
0746 }
0747
0748 static ssize_t cdpower_show(struct device *dev, struct device_attribute *attr,
0749 char *buf)
0750 {
0751 return sysfs_emit(buf, "%d\n", get_optd_power_state());
0752 }
0753
0754 static ssize_t cdpower_store(struct device *dev, struct device_attribute *attr,
0755 const char *buf, size_t count)
0756 {
0757 int err, val;
0758
0759 err = kstrtoint(buf, 10, &val);
0760 if (err)
0761 return err;
0762 set_optd_power_state(val);
0763 return count;
0764 }
0765
0766 static DEVICE_ATTR_RO(numbatt);
0767 static DEVICE_ATTR_RO(lcdtype);
0768 static DEVICE_ATTR_RW(mute);
0769 static DEVICE_ATTR_RW(sticky_key);
0770 static DEVICE_ATTR_RW(eco_mode);
0771 static DEVICE_ATTR_RW(ac_brightness);
0772 static DEVICE_ATTR_RW(dc_brightness);
0773 static DEVICE_ATTR_RW(current_brightness);
0774 static DEVICE_ATTR_RW(cdpower);
0775
0776 static struct attribute *pcc_sysfs_entries[] = {
0777 &dev_attr_numbatt.attr,
0778 &dev_attr_lcdtype.attr,
0779 &dev_attr_mute.attr,
0780 &dev_attr_sticky_key.attr,
0781 &dev_attr_eco_mode.attr,
0782 &dev_attr_ac_brightness.attr,
0783 &dev_attr_dc_brightness.attr,
0784 &dev_attr_current_brightness.attr,
0785 &dev_attr_cdpower.attr,
0786 NULL,
0787 };
0788
0789 static const struct attribute_group pcc_attr_group = {
0790 .name = NULL,
0791 .attrs = pcc_sysfs_entries,
0792 };
0793
0794
0795
0796
0797 static int sleep_keydown_seen;
0798 static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
0799 {
0800 struct input_dev *hotk_input_dev = pcc->input_dev;
0801 int rc;
0802 unsigned long long result;
0803 unsigned int key;
0804 unsigned int updown;
0805
0806 rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY,
0807 NULL, &result);
0808 if (ACPI_FAILURE(rc)) {
0809 pr_err("error getting hotkey status\n");
0810 return;
0811 }
0812
0813 key = result & 0xf;
0814 updown = result & 0x80;
0815
0816
0817 if (key == 7 || key == 10) {
0818 if (updown)
0819 sleep_keydown_seen = 1;
0820 if (!sleep_keydown_seen)
0821 sparse_keymap_report_event(hotk_input_dev,
0822 key, 0x80, false);
0823 }
0824
0825
0826
0827
0828
0829 if ((key == 1 || key == 2) && acpi_video_handles_brightness_key_presses())
0830 return;
0831
0832 if (!sparse_keymap_report_event(hotk_input_dev, key, updown, false))
0833 pr_err("Unknown hotkey event: 0x%04llx\n", result);
0834 }
0835
0836 static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event)
0837 {
0838 struct pcc_acpi *pcc = acpi_driver_data(device);
0839
0840 switch (event) {
0841 case HKEY_NOTIFY:
0842 acpi_pcc_generate_keyinput(pcc);
0843 break;
0844 default:
0845
0846 break;
0847 }
0848 }
0849
0850 static void pcc_optd_notify(acpi_handle handle, u32 event, void *data)
0851 {
0852 if (event != ACPI_NOTIFY_EJECT_REQUEST)
0853 return;
0854
0855 set_optd_power_state(0);
0856 }
0857
0858 static int pcc_register_optd_notifier(struct pcc_acpi *pcc, char *node)
0859 {
0860 acpi_status status;
0861 acpi_handle handle;
0862
0863 status = acpi_get_handle(NULL, node, &handle);
0864
0865 if (ACPI_SUCCESS(status)) {
0866 status = acpi_install_notify_handler(handle,
0867 ACPI_SYSTEM_NOTIFY,
0868 pcc_optd_notify, pcc);
0869 if (ACPI_FAILURE(status))
0870 pr_err("Failed to register notify on %s\n", node);
0871 } else
0872 return -ENODEV;
0873
0874 return 0;
0875 }
0876
0877 static void pcc_unregister_optd_notifier(struct pcc_acpi *pcc, char *node)
0878 {
0879 acpi_status status = AE_OK;
0880 acpi_handle handle;
0881
0882 status = acpi_get_handle(NULL, node, &handle);
0883
0884 if (ACPI_SUCCESS(status)) {
0885 status = acpi_remove_notify_handler(handle,
0886 ACPI_SYSTEM_NOTIFY,
0887 pcc_optd_notify);
0888 if (ACPI_FAILURE(status))
0889 pr_err("Error removing optd notify handler %s\n",
0890 node);
0891 }
0892 }
0893
0894 static int acpi_pcc_init_input(struct pcc_acpi *pcc)
0895 {
0896 struct input_dev *input_dev;
0897 int error;
0898
0899 input_dev = input_allocate_device();
0900 if (!input_dev)
0901 return -ENOMEM;
0902
0903 input_dev->name = ACPI_PCC_DRIVER_NAME;
0904 input_dev->phys = ACPI_PCC_INPUT_PHYS;
0905 input_dev->id.bustype = BUS_HOST;
0906 input_dev->id.vendor = 0x0001;
0907 input_dev->id.product = 0x0001;
0908 input_dev->id.version = 0x0100;
0909
0910 error = sparse_keymap_setup(input_dev, panasonic_keymap, NULL);
0911 if (error) {
0912 pr_err("Unable to setup input device keymap\n");
0913 goto err_free_dev;
0914 }
0915
0916 error = input_register_device(input_dev);
0917 if (error) {
0918 pr_err("Unable to register input device\n");
0919 goto err_free_dev;
0920 }
0921
0922 pcc->input_dev = input_dev;
0923 return 0;
0924
0925 err_free_dev:
0926 input_free_device(input_dev);
0927 return error;
0928 }
0929
0930
0931
0932 #ifdef CONFIG_PM_SLEEP
0933 static int acpi_pcc_hotkey_resume(struct device *dev)
0934 {
0935 struct pcc_acpi *pcc;
0936
0937 if (!dev)
0938 return -EINVAL;
0939
0940 pcc = acpi_driver_data(to_acpi_device(dev));
0941 if (!pcc)
0942 return -EINVAL;
0943
0944 acpi_pcc_write_sset(pcc, SINF_MUTE, pcc->mute);
0945 acpi_pcc_write_sset(pcc, SINF_ECO_MODE, pcc->eco_mode);
0946 acpi_pcc_write_sset(pcc, SINF_STICKY_KEY, pcc->sticky_key);
0947 acpi_pcc_write_sset(pcc, SINF_AC_CUR_BRIGHT, pcc->ac_brightness);
0948 acpi_pcc_write_sset(pcc, SINF_DC_CUR_BRIGHT, pcc->dc_brightness);
0949 acpi_pcc_write_sset(pcc, SINF_CUR_BRIGHT, pcc->current_brightness);
0950
0951 return 0;
0952 }
0953 #endif
0954
0955 static int acpi_pcc_hotkey_add(struct acpi_device *device)
0956 {
0957 struct backlight_properties props;
0958 struct pcc_acpi *pcc;
0959 int num_sifr, result;
0960
0961 if (!device)
0962 return -EINVAL;
0963
0964 num_sifr = acpi_pcc_get_sqty(device);
0965
0966 if (num_sifr < 0 || num_sifr > 255) {
0967 pr_err("num_sifr out of range");
0968 return -ENODEV;
0969 }
0970
0971 pcc = kzalloc(sizeof(struct pcc_acpi), GFP_KERNEL);
0972 if (!pcc) {
0973 pr_err("Couldn't allocate mem for pcc");
0974 return -ENOMEM;
0975 }
0976
0977 pcc->sinf = kcalloc(num_sifr + 1, sizeof(u32), GFP_KERNEL);
0978 if (!pcc->sinf) {
0979 result = -ENOMEM;
0980 goto out_hotkey;
0981 }
0982
0983 pcc->device = device;
0984 pcc->handle = device->handle;
0985 pcc->num_sifr = num_sifr;
0986 device->driver_data = pcc;
0987 strcpy(acpi_device_name(device), ACPI_PCC_DEVICE_NAME);
0988 strcpy(acpi_device_class(device), ACPI_PCC_CLASS);
0989
0990 result = acpi_pcc_init_input(pcc);
0991 if (result) {
0992 pr_err("Error installing keyinput handler\n");
0993 goto out_sinf;
0994 }
0995
0996 if (!acpi_pcc_retrieve_biosdata(pcc)) {
0997 result = -EIO;
0998 pr_err("Couldn't retrieve BIOS data\n");
0999 goto out_input;
1000 }
1001
1002 if (acpi_video_get_backlight_type() == acpi_backlight_vendor) {
1003
1004 memset(&props, 0, sizeof(struct backlight_properties));
1005 props.type = BACKLIGHT_PLATFORM;
1006 props.max_brightness = pcc->sinf[SINF_AC_MAX_BRIGHT];
1007
1008 pcc->backlight = backlight_device_register("panasonic", NULL, pcc,
1009 &pcc_backlight_ops, &props);
1010 if (IS_ERR(pcc->backlight)) {
1011 result = PTR_ERR(pcc->backlight);
1012 goto out_input;
1013 }
1014
1015
1016 pcc->backlight->props.brightness = pcc->sinf[SINF_AC_CUR_BRIGHT];
1017 }
1018
1019
1020 acpi_pcc_write_sset(pcc, SINF_STICKY_KEY, 0);
1021 pcc->sticky_key = 0;
1022
1023 pcc->eco_mode = pcc->sinf[SINF_ECO_MODE];
1024 pcc->mute = pcc->sinf[SINF_MUTE];
1025 pcc->ac_brightness = pcc->sinf[SINF_AC_CUR_BRIGHT];
1026 pcc->dc_brightness = pcc->sinf[SINF_DC_CUR_BRIGHT];
1027 pcc->current_brightness = pcc->sinf[SINF_CUR_BRIGHT];
1028
1029
1030 result = sysfs_create_group(&device->dev.kobj, &pcc_attr_group);
1031 if (result)
1032 goto out_backlight;
1033
1034
1035 if (ACPI_SUCCESS(check_optd_present())) {
1036 pcc->platform = platform_device_register_simple("panasonic",
1037 -1, NULL, 0);
1038 if (IS_ERR(pcc->platform)) {
1039 result = PTR_ERR(pcc->platform);
1040 goto out_backlight;
1041 }
1042 result = device_create_file(&pcc->platform->dev,
1043 &dev_attr_cdpower);
1044 pcc_register_optd_notifier(pcc, "\\_SB.PCI0.EHCI.ERHB.OPTD");
1045 if (result)
1046 goto out_platform;
1047 } else {
1048 pcc->platform = NULL;
1049 }
1050
1051 i8042_install_filter(panasonic_i8042_filter);
1052 return 0;
1053
1054 out_platform:
1055 platform_device_unregister(pcc->platform);
1056 out_backlight:
1057 backlight_device_unregister(pcc->backlight);
1058 out_input:
1059 input_unregister_device(pcc->input_dev);
1060 out_sinf:
1061 kfree(pcc->sinf);
1062 out_hotkey:
1063 kfree(pcc);
1064
1065 return result;
1066 }
1067
1068 static int acpi_pcc_hotkey_remove(struct acpi_device *device)
1069 {
1070 struct pcc_acpi *pcc = acpi_driver_data(device);
1071
1072 if (!device || !pcc)
1073 return -EINVAL;
1074
1075 i8042_remove_filter(panasonic_i8042_filter);
1076
1077 if (pcc->platform) {
1078 device_remove_file(&pcc->platform->dev, &dev_attr_cdpower);
1079 platform_device_unregister(pcc->platform);
1080 }
1081 pcc_unregister_optd_notifier(pcc, "\\_SB.PCI0.EHCI.ERHB.OPTD");
1082
1083 sysfs_remove_group(&device->dev.kobj, &pcc_attr_group);
1084
1085 backlight_device_unregister(pcc->backlight);
1086
1087 input_unregister_device(pcc->input_dev);
1088
1089 kfree(pcc->sinf);
1090 kfree(pcc);
1091
1092 return 0;
1093 }
1094
1095 module_acpi_driver(acpi_pcc_driver);