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