]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/platform/x86/fujitsu-laptop.c
platform/x86: fujitsu-laptop: do not log set_lcd_level() failures in bl_update_status()
[mirror_ubuntu-bionic-kernel.git] / drivers / platform / x86 / fujitsu-laptop.c
1 /*-*-linux-c-*-*/
2
3 /*
4 Copyright (C) 2007,2008 Jonathan Woithe <jwoithe@just42.net>
5 Copyright (C) 2008 Peter Gruber <nokos@gmx.net>
6 Copyright (C) 2008 Tony Vroon <tony@linx.net>
7 Based on earlier work:
8 Copyright (C) 2003 Shane Spencer <shane@bogomip.com>
9 Adrian Yee <brewt-fujitsu@brewt.org>
10
11 Templated from msi-laptop.c and thinkpad_acpi.c which is copyright
12 by its respective authors.
13
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27 02110-1301, USA.
28 */
29
30 /*
31 * fujitsu-laptop.c - Fujitsu laptop support, providing access to additional
32 * features made available on a range of Fujitsu laptops including the
33 * P2xxx/P5xxx/S6xxx/S7xxx series.
34 *
35 * This driver implements a vendor-specific backlight control interface for
36 * Fujitsu laptops and provides support for hotkeys present on certain Fujitsu
37 * laptops.
38 *
39 * This driver has been tested on a Fujitsu Lifebook S6410, S7020 and
40 * P8010. It should work on most P-series and S-series Lifebooks, but
41 * YMMV.
42 *
43 * The module parameter use_alt_lcd_levels switches between different ACPI
44 * brightness controls which are used by different Fujitsu laptops. In most
45 * cases the correct method is automatically detected. "use_alt_lcd_levels=1"
46 * is applicable for a Fujitsu Lifebook S6410 if autodetection fails.
47 *
48 */
49
50 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
51
52 #include <linux/module.h>
53 #include <linux/kernel.h>
54 #include <linux/init.h>
55 #include <linux/acpi.h>
56 #include <linux/dmi.h>
57 #include <linux/backlight.h>
58 #include <linux/fb.h>
59 #include <linux/input.h>
60 #include <linux/input/sparse-keymap.h>
61 #include <linux/kfifo.h>
62 #include <linux/platform_device.h>
63 #include <linux/slab.h>
64 #if IS_ENABLED(CONFIG_LEDS_CLASS)
65 #include <linux/leds.h>
66 #endif
67 #include <acpi/video.h>
68
69 #define FUJITSU_DRIVER_VERSION "0.6.0"
70
71 #define FUJITSU_LCD_N_LEVELS 8
72
73 #define ACPI_FUJITSU_CLASS "fujitsu"
74 #define ACPI_FUJITSU_BL_HID "FUJ02B1"
75 #define ACPI_FUJITSU_BL_DRIVER_NAME "Fujitsu laptop FUJ02B1 ACPI brightness driver"
76 #define ACPI_FUJITSU_BL_DEVICE_NAME "Fujitsu FUJ02B1"
77 #define ACPI_FUJITSU_LAPTOP_HID "FUJ02E3"
78 #define ACPI_FUJITSU_LAPTOP_DRIVER_NAME "Fujitsu laptop FUJ02E3 ACPI hotkeys driver"
79 #define ACPI_FUJITSU_LAPTOP_DEVICE_NAME "Fujitsu FUJ02E3"
80
81 #define ACPI_FUJITSU_NOTIFY_CODE1 0x80
82
83 /* FUNC interface - command values */
84 #define FUNC_FLAGS 0x1000
85 #define FUNC_LEDS 0x1001
86 #define FUNC_BUTTONS 0x1002
87 #define FUNC_BACKLIGHT 0x1004
88
89 /* FUNC interface - responses */
90 #define UNSUPPORTED_CMD 0x80000000
91
92 /* FUNC interface - status flags */
93 #define FLAG_RFKILL 0x020
94 #define FLAG_LID 0x100
95 #define FLAG_DOCK 0x200
96
97 #if IS_ENABLED(CONFIG_LEDS_CLASS)
98 /* FUNC interface - LED control */
99 #define FUNC_LED_OFF 0x1
100 #define FUNC_LED_ON 0x30001
101 #define KEYBOARD_LAMPS 0x100
102 #define LOGOLAMP_POWERON 0x2000
103 #define LOGOLAMP_ALWAYS 0x4000
104 #define RADIO_LED_ON 0x20
105 #define ECO_LED 0x10000
106 #define ECO_LED_ON 0x80000
107 #endif
108
109 /* Hotkey details */
110 #define KEY1_CODE 0x410 /* codes for the keys in the GIRB register */
111 #define KEY2_CODE 0x411
112 #define KEY3_CODE 0x412
113 #define KEY4_CODE 0x413
114 #define KEY5_CODE 0x420
115
116 #define MAX_HOTKEY_RINGBUFFER_SIZE 100
117 #define RINGBUFFERSIZE 40
118
119 /* Debugging */
120 #define FUJLAPTOP_DBG_ERROR 0x0001
121 #define FUJLAPTOP_DBG_WARN 0x0002
122 #define FUJLAPTOP_DBG_INFO 0x0004
123 #define FUJLAPTOP_DBG_TRACE 0x0008
124
125 #ifdef CONFIG_FUJITSU_LAPTOP_DEBUG
126 #define vdbg_printk(a_dbg_level, format, arg...) \
127 do { if (dbg_level & a_dbg_level) \
128 printk(KERN_DEBUG pr_fmt("%s: " format), __func__, ## arg); \
129 } while (0)
130 #else
131 #define vdbg_printk(a_dbg_level, format, arg...) \
132 do { } while (0)
133 #endif
134
135 /* Device controlling the backlight and associated keys */
136 struct fujitsu_bl {
137 acpi_handle acpi_handle;
138 struct acpi_device *dev;
139 struct input_dev *input;
140 char phys[32];
141 struct backlight_device *bl_device;
142
143 unsigned int max_brightness;
144 unsigned int brightness_changed;
145 unsigned int brightness_level;
146 };
147
148 static struct fujitsu_bl *fujitsu_bl;
149 static int use_alt_lcd_levels = -1;
150 static bool disable_brightness_adjust;
151
152 /* Device used to access hotkeys and other features on the laptop */
153 struct fujitsu_laptop {
154 acpi_handle acpi_handle;
155 struct acpi_device *dev;
156 struct input_dev *input;
157 char phys[32];
158 struct platform_device *pf_device;
159 struct kfifo fifo;
160 spinlock_t fifo_lock;
161 int flags_supported;
162 int flags_state;
163 int logolamp_registered;
164 int kblamps_registered;
165 int radio_led_registered;
166 int eco_led_registered;
167 };
168
169 static struct fujitsu_laptop *fujitsu_laptop;
170
171 #if IS_ENABLED(CONFIG_LEDS_CLASS)
172 static enum led_brightness logolamp_get(struct led_classdev *cdev);
173 static int logolamp_set(struct led_classdev *cdev,
174 enum led_brightness brightness);
175
176 static struct led_classdev logolamp_led = {
177 .name = "fujitsu::logolamp",
178 .brightness_get = logolamp_get,
179 .brightness_set_blocking = logolamp_set
180 };
181
182 static enum led_brightness kblamps_get(struct led_classdev *cdev);
183 static int kblamps_set(struct led_classdev *cdev,
184 enum led_brightness brightness);
185
186 static struct led_classdev kblamps_led = {
187 .name = "fujitsu::kblamps",
188 .brightness_get = kblamps_get,
189 .brightness_set_blocking = kblamps_set
190 };
191
192 static enum led_brightness radio_led_get(struct led_classdev *cdev);
193 static int radio_led_set(struct led_classdev *cdev,
194 enum led_brightness brightness);
195
196 static struct led_classdev radio_led = {
197 .name = "fujitsu::radio_led",
198 .default_trigger = "rfkill-any",
199 .brightness_get = radio_led_get,
200 .brightness_set_blocking = radio_led_set
201 };
202
203 static enum led_brightness eco_led_get(struct led_classdev *cdev);
204 static int eco_led_set(struct led_classdev *cdev,
205 enum led_brightness brightness);
206
207 static struct led_classdev eco_led = {
208 .name = "fujitsu::eco_led",
209 .brightness_get = eco_led_get,
210 .brightness_set_blocking = eco_led_set
211 };
212 #endif
213
214 #ifdef CONFIG_FUJITSU_LAPTOP_DEBUG
215 static u32 dbg_level = 0x03;
216 #endif
217
218 /* Fujitsu ACPI interface function */
219
220 static int call_fext_func(int func, int op, int feature, int state)
221 {
222 union acpi_object params[4] = {
223 { .integer.type = ACPI_TYPE_INTEGER, .integer.value = func },
224 { .integer.type = ACPI_TYPE_INTEGER, .integer.value = op },
225 { .integer.type = ACPI_TYPE_INTEGER, .integer.value = feature },
226 { .integer.type = ACPI_TYPE_INTEGER, .integer.value = state }
227 };
228 struct acpi_object_list arg_list = { 4, params };
229 unsigned long long value;
230 acpi_status status;
231
232 status = acpi_evaluate_integer(fujitsu_laptop->acpi_handle, "FUNC",
233 &arg_list, &value);
234 if (ACPI_FAILURE(status)) {
235 vdbg_printk(FUJLAPTOP_DBG_ERROR, "Failed to evaluate FUNC\n");
236 return -ENODEV;
237 }
238
239 vdbg_printk(FUJLAPTOP_DBG_TRACE, "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) returned 0x%x\n",
240 func, op, feature, state, (int)value);
241 return value;
242 }
243
244 #if IS_ENABLED(CONFIG_LEDS_CLASS)
245 /* LED class callbacks */
246
247 static int logolamp_set(struct led_classdev *cdev,
248 enum led_brightness brightness)
249 {
250 int poweron = FUNC_LED_ON, always = FUNC_LED_ON;
251 int ret;
252
253 if (brightness < LED_HALF)
254 poweron = FUNC_LED_OFF;
255
256 if (brightness < LED_FULL)
257 always = FUNC_LED_OFF;
258
259 ret = call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, poweron);
260 if (ret < 0)
261 return ret;
262
263 return call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, always);
264 }
265
266 static int kblamps_set(struct led_classdev *cdev,
267 enum led_brightness brightness)
268 {
269 if (brightness >= LED_FULL)
270 return call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, FUNC_LED_ON);
271 else
272 return call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, FUNC_LED_OFF);
273 }
274
275 static int radio_led_set(struct led_classdev *cdev,
276 enum led_brightness brightness)
277 {
278 if (brightness >= LED_FULL)
279 return call_fext_func(FUNC_FLAGS, 0x5, RADIO_LED_ON, RADIO_LED_ON);
280 else
281 return call_fext_func(FUNC_FLAGS, 0x5, RADIO_LED_ON, 0x0);
282 }
283
284 static int eco_led_set(struct led_classdev *cdev,
285 enum led_brightness brightness)
286 {
287 int curr;
288
289 curr = call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0);
290 if (brightness >= LED_FULL)
291 return call_fext_func(FUNC_LEDS, 0x1, ECO_LED, curr | ECO_LED_ON);
292 else
293 return call_fext_func(FUNC_LEDS, 0x1, ECO_LED, curr & ~ECO_LED_ON);
294 }
295
296 static enum led_brightness logolamp_get(struct led_classdev *cdev)
297 {
298 int ret;
299
300 ret = call_fext_func(FUNC_LEDS, 0x2, LOGOLAMP_ALWAYS, 0x0);
301 if (ret == FUNC_LED_ON)
302 return LED_FULL;
303
304 ret = call_fext_func(FUNC_LEDS, 0x2, LOGOLAMP_POWERON, 0x0);
305 if (ret == FUNC_LED_ON)
306 return LED_HALF;
307
308 return LED_OFF;
309 }
310
311 static enum led_brightness kblamps_get(struct led_classdev *cdev)
312 {
313 enum led_brightness brightness = LED_OFF;
314
315 if (call_fext_func(FUNC_LEDS, 0x2, KEYBOARD_LAMPS, 0x0) == FUNC_LED_ON)
316 brightness = LED_FULL;
317
318 return brightness;
319 }
320
321 static enum led_brightness radio_led_get(struct led_classdev *cdev)
322 {
323 enum led_brightness brightness = LED_OFF;
324
325 if (call_fext_func(FUNC_FLAGS, 0x4, 0x0, 0x0) & RADIO_LED_ON)
326 brightness = LED_FULL;
327
328 return brightness;
329 }
330
331 static enum led_brightness eco_led_get(struct led_classdev *cdev)
332 {
333 enum led_brightness brightness = LED_OFF;
334
335 if (call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0) & ECO_LED_ON)
336 brightness = LED_FULL;
337
338 return brightness;
339 }
340 #endif
341
342 /* Hardware access for LCD brightness control */
343
344 static int set_lcd_level(int level)
345 {
346 acpi_status status;
347 char *method;
348
349 switch (use_alt_lcd_levels) {
350 case -1:
351 if (acpi_has_method(fujitsu_bl->acpi_handle, "SBL2"))
352 method = "SBL2";
353 else
354 method = "SBLL";
355 break;
356 case 1:
357 method = "SBL2";
358 break;
359 default:
360 method = "SBLL";
361 break;
362 }
363
364 vdbg_printk(FUJLAPTOP_DBG_TRACE, "set lcd level via %s [%d]\n",
365 method, level);
366
367 if (level < 0 || level >= fujitsu_bl->max_brightness)
368 return -EINVAL;
369
370 status = acpi_execute_simple_method(fujitsu_bl->acpi_handle, method,
371 level);
372 if (ACPI_FAILURE(status)) {
373 vdbg_printk(FUJLAPTOP_DBG_ERROR, "Failed to evaluate %s\n",
374 method);
375 return -ENODEV;
376 }
377
378 fujitsu_bl->brightness_level = level;
379
380 return 0;
381 }
382
383 static int get_lcd_level(void)
384 {
385 unsigned long long state = 0;
386 acpi_status status = AE_OK;
387
388 vdbg_printk(FUJLAPTOP_DBG_TRACE, "get lcd level via GBLL\n");
389
390 status = acpi_evaluate_integer(fujitsu_bl->acpi_handle, "GBLL", NULL,
391 &state);
392 if (ACPI_FAILURE(status))
393 return 0;
394
395 fujitsu_bl->brightness_level = state & 0x0fffffff;
396
397 if (state & 0x80000000)
398 fujitsu_bl->brightness_changed = 1;
399 else
400 fujitsu_bl->brightness_changed = 0;
401
402 return fujitsu_bl->brightness_level;
403 }
404
405 static int get_max_brightness(void)
406 {
407 unsigned long long state = 0;
408 acpi_status status = AE_OK;
409
410 vdbg_printk(FUJLAPTOP_DBG_TRACE, "get max lcd level via RBLL\n");
411
412 status = acpi_evaluate_integer(fujitsu_bl->acpi_handle, "RBLL", NULL,
413 &state);
414 if (ACPI_FAILURE(status))
415 return -1;
416
417 fujitsu_bl->max_brightness = state;
418
419 return fujitsu_bl->max_brightness;
420 }
421
422 /* Backlight device stuff */
423
424 static int bl_get_brightness(struct backlight_device *b)
425 {
426 return get_lcd_level();
427 }
428
429 static int bl_update_status(struct backlight_device *b)
430 {
431 if (b->props.power == FB_BLANK_POWERDOWN)
432 call_fext_func(FUNC_BACKLIGHT, 0x1, 0x4, 0x3);
433 else
434 call_fext_func(FUNC_BACKLIGHT, 0x1, 0x4, 0x0);
435
436 return set_lcd_level(b->props.brightness);
437 }
438
439 static const struct backlight_ops fujitsu_bl_ops = {
440 .get_brightness = bl_get_brightness,
441 .update_status = bl_update_status,
442 };
443
444 static ssize_t lid_show(struct device *dev, struct device_attribute *attr,
445 char *buf)
446 {
447 if (!(fujitsu_laptop->flags_supported & FLAG_LID))
448 return sprintf(buf, "unknown\n");
449 if (fujitsu_laptop->flags_state & FLAG_LID)
450 return sprintf(buf, "open\n");
451 else
452 return sprintf(buf, "closed\n");
453 }
454
455 static ssize_t dock_show(struct device *dev, struct device_attribute *attr,
456 char *buf)
457 {
458 if (!(fujitsu_laptop->flags_supported & FLAG_DOCK))
459 return sprintf(buf, "unknown\n");
460 if (fujitsu_laptop->flags_state & FLAG_DOCK)
461 return sprintf(buf, "docked\n");
462 else
463 return sprintf(buf, "undocked\n");
464 }
465
466 static ssize_t radios_show(struct device *dev, struct device_attribute *attr,
467 char *buf)
468 {
469 if (!(fujitsu_laptop->flags_supported & FLAG_RFKILL))
470 return sprintf(buf, "unknown\n");
471 if (fujitsu_laptop->flags_state & FLAG_RFKILL)
472 return sprintf(buf, "on\n");
473 else
474 return sprintf(buf, "killed\n");
475 }
476
477 static DEVICE_ATTR_RO(lid);
478 static DEVICE_ATTR_RO(dock);
479 static DEVICE_ATTR_RO(radios);
480
481 static struct attribute *fujitsu_pf_attributes[] = {
482 &dev_attr_lid.attr,
483 &dev_attr_dock.attr,
484 &dev_attr_radios.attr,
485 NULL
486 };
487
488 static struct attribute_group fujitsu_pf_attribute_group = {
489 .attrs = fujitsu_pf_attributes
490 };
491
492 static struct platform_driver fujitsu_pf_driver = {
493 .driver = {
494 .name = "fujitsu-laptop",
495 }
496 };
497
498 /* ACPI device for LCD brightness control */
499
500 static const struct key_entry keymap_backlight[] = {
501 { KE_KEY, true, { KEY_BRIGHTNESSUP } },
502 { KE_KEY, false, { KEY_BRIGHTNESSDOWN } },
503 { KE_END, 0 }
504 };
505
506 static int acpi_fujitsu_bl_input_setup(struct acpi_device *device)
507 {
508 struct fujitsu_bl *fujitsu_bl = acpi_driver_data(device);
509 int ret;
510
511 fujitsu_bl->input = devm_input_allocate_device(&device->dev);
512 if (!fujitsu_bl->input)
513 return -ENOMEM;
514
515 snprintf(fujitsu_bl->phys, sizeof(fujitsu_bl->phys),
516 "%s/video/input0", acpi_device_hid(device));
517
518 fujitsu_bl->input->name = acpi_device_name(device);
519 fujitsu_bl->input->phys = fujitsu_bl->phys;
520 fujitsu_bl->input->id.bustype = BUS_HOST;
521 fujitsu_bl->input->id.product = 0x06;
522
523 ret = sparse_keymap_setup(fujitsu_bl->input, keymap_backlight, NULL);
524 if (ret)
525 return ret;
526
527 return input_register_device(fujitsu_bl->input);
528 }
529
530 static int fujitsu_backlight_register(struct acpi_device *device)
531 {
532 const struct backlight_properties props = {
533 .brightness = fujitsu_bl->brightness_level,
534 .max_brightness = fujitsu_bl->max_brightness - 1,
535 .type = BACKLIGHT_PLATFORM
536 };
537 struct backlight_device *bd;
538
539 bd = devm_backlight_device_register(&device->dev, "fujitsu-laptop",
540 &device->dev, NULL,
541 &fujitsu_bl_ops, &props);
542 if (IS_ERR(bd))
543 return PTR_ERR(bd);
544
545 fujitsu_bl->bl_device = bd;
546
547 return 0;
548 }
549
550 static int acpi_fujitsu_bl_add(struct acpi_device *device)
551 {
552 int state = 0;
553 int error;
554
555 if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
556 return -ENODEV;
557
558 if (!device)
559 return -EINVAL;
560
561 fujitsu_bl->acpi_handle = device->handle;
562 sprintf(acpi_device_name(device), "%s", ACPI_FUJITSU_BL_DEVICE_NAME);
563 sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS);
564 device->driver_data = fujitsu_bl;
565
566 error = acpi_fujitsu_bl_input_setup(device);
567 if (error)
568 return error;
569
570 error = acpi_bus_update_power(fujitsu_bl->acpi_handle, &state);
571 if (error) {
572 pr_err("Error reading power state\n");
573 return error;
574 }
575
576 pr_info("ACPI: %s [%s] (%s)\n",
577 acpi_device_name(device), acpi_device_bid(device),
578 !device->power.state ? "on" : "off");
579
580 fujitsu_bl->dev = device;
581
582 if (acpi_has_method(device->handle, METHOD_NAME__INI)) {
583 vdbg_printk(FUJLAPTOP_DBG_INFO, "Invoking _INI\n");
584 if (ACPI_FAILURE
585 (acpi_evaluate_object
586 (device->handle, METHOD_NAME__INI, NULL, NULL)))
587 pr_err("_INI Method failed\n");
588 }
589
590 if (get_max_brightness() <= 0)
591 fujitsu_bl->max_brightness = FUJITSU_LCD_N_LEVELS;
592 get_lcd_level();
593
594 error = fujitsu_backlight_register(device);
595 if (error)
596 return error;
597
598 return 0;
599 }
600
601 /* Brightness notify */
602
603 static void acpi_fujitsu_bl_notify(struct acpi_device *device, u32 event)
604 {
605 struct input_dev *input;
606 int oldb, newb;
607
608 input = fujitsu_bl->input;
609
610 if (event != ACPI_FUJITSU_NOTIFY_CODE1) {
611 vdbg_printk(FUJLAPTOP_DBG_WARN,
612 "unsupported event [0x%x]\n", event);
613 sparse_keymap_report_event(input, -1, 1, true);
614 return;
615 }
616
617 oldb = fujitsu_bl->brightness_level;
618 get_lcd_level();
619 newb = fujitsu_bl->brightness_level;
620
621 vdbg_printk(FUJLAPTOP_DBG_TRACE,
622 "brightness button event [%i -> %i (%i)]\n",
623 oldb, newb, fujitsu_bl->brightness_changed);
624
625 if (oldb == newb)
626 return;
627
628 if (!disable_brightness_adjust)
629 set_lcd_level(newb);
630
631 sparse_keymap_report_event(input, oldb < newb, 1, true);
632 }
633
634 /* ACPI device for hotkey handling */
635
636 static const struct key_entry keymap_default[] = {
637 { KE_KEY, KEY1_CODE, { KEY_PROG1 } },
638 { KE_KEY, KEY2_CODE, { KEY_PROG2 } },
639 { KE_KEY, KEY3_CODE, { KEY_PROG3 } },
640 { KE_KEY, KEY4_CODE, { KEY_PROG4 } },
641 { KE_KEY, KEY5_CODE, { KEY_RFKILL } },
642 { KE_KEY, BIT(26), { KEY_TOUCHPAD_TOGGLE } },
643 { KE_END, 0 }
644 };
645
646 static const struct key_entry keymap_s64x0[] = {
647 { KE_KEY, KEY1_CODE, { KEY_SCREENLOCK } }, /* "Lock" */
648 { KE_KEY, KEY2_CODE, { KEY_HELP } }, /* "Mobility Center */
649 { KE_KEY, KEY3_CODE, { KEY_PROG3 } },
650 { KE_KEY, KEY4_CODE, { KEY_PROG4 } },
651 { KE_END, 0 }
652 };
653
654 static const struct key_entry keymap_p8010[] = {
655 { KE_KEY, KEY1_CODE, { KEY_HELP } }, /* "Support" */
656 { KE_KEY, KEY2_CODE, { KEY_PROG2 } },
657 { KE_KEY, KEY3_CODE, { KEY_SWITCHVIDEOMODE } }, /* "Presentation" */
658 { KE_KEY, KEY4_CODE, { KEY_WWW } }, /* "WWW" */
659 { KE_END, 0 }
660 };
661
662 static const struct key_entry *keymap = keymap_default;
663
664 static int fujitsu_laptop_dmi_keymap_override(const struct dmi_system_id *id)
665 {
666 pr_info("Identified laptop model '%s'\n", id->ident);
667 keymap = id->driver_data;
668 return 1;
669 }
670
671 static const struct dmi_system_id fujitsu_laptop_dmi_table[] = {
672 {
673 .callback = fujitsu_laptop_dmi_keymap_override,
674 .ident = "Fujitsu Siemens S6410",
675 .matches = {
676 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
677 DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6410"),
678 },
679 .driver_data = (void *)keymap_s64x0
680 },
681 {
682 .callback = fujitsu_laptop_dmi_keymap_override,
683 .ident = "Fujitsu Siemens S6420",
684 .matches = {
685 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
686 DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6420"),
687 },
688 .driver_data = (void *)keymap_s64x0
689 },
690 {
691 .callback = fujitsu_laptop_dmi_keymap_override,
692 .ident = "Fujitsu LifeBook P8010",
693 .matches = {
694 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
695 DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P8010"),
696 },
697 .driver_data = (void *)keymap_p8010
698 },
699 {}
700 };
701
702 static int acpi_fujitsu_laptop_input_setup(struct acpi_device *device)
703 {
704 struct fujitsu_laptop *fujitsu_laptop = acpi_driver_data(device);
705 int ret;
706
707 fujitsu_laptop->input = devm_input_allocate_device(&device->dev);
708 if (!fujitsu_laptop->input)
709 return -ENOMEM;
710
711 snprintf(fujitsu_laptop->phys, sizeof(fujitsu_laptop->phys),
712 "%s/video/input0", acpi_device_hid(device));
713
714 fujitsu_laptop->input->name = acpi_device_name(device);
715 fujitsu_laptop->input->phys = fujitsu_laptop->phys;
716 fujitsu_laptop->input->id.bustype = BUS_HOST;
717 fujitsu_laptop->input->id.product = 0x06;
718
719 dmi_check_system(fujitsu_laptop_dmi_table);
720 ret = sparse_keymap_setup(fujitsu_laptop->input, keymap, NULL);
721 if (ret)
722 return ret;
723
724 return input_register_device(fujitsu_laptop->input);
725 }
726
727 static int fujitsu_laptop_platform_add(void)
728 {
729 int ret;
730
731 fujitsu_laptop->pf_device = platform_device_alloc("fujitsu-laptop", -1);
732 if (!fujitsu_laptop->pf_device)
733 return -ENOMEM;
734
735 ret = platform_device_add(fujitsu_laptop->pf_device);
736 if (ret)
737 goto err_put_platform_device;
738
739 ret = sysfs_create_group(&fujitsu_laptop->pf_device->dev.kobj,
740 &fujitsu_pf_attribute_group);
741 if (ret)
742 goto err_del_platform_device;
743
744 return 0;
745
746 err_del_platform_device:
747 platform_device_del(fujitsu_laptop->pf_device);
748 err_put_platform_device:
749 platform_device_put(fujitsu_laptop->pf_device);
750
751 return ret;
752 }
753
754 static void fujitsu_laptop_platform_remove(void)
755 {
756 sysfs_remove_group(&fujitsu_laptop->pf_device->dev.kobj,
757 &fujitsu_pf_attribute_group);
758 platform_device_unregister(fujitsu_laptop->pf_device);
759 }
760
761 static int acpi_fujitsu_laptop_add(struct acpi_device *device)
762 {
763 int result = 0;
764 int state = 0;
765 int error;
766 int i;
767
768 if (!device)
769 return -EINVAL;
770
771 fujitsu_laptop->acpi_handle = device->handle;
772 sprintf(acpi_device_name(device), "%s",
773 ACPI_FUJITSU_LAPTOP_DEVICE_NAME);
774 sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS);
775 device->driver_data = fujitsu_laptop;
776
777 /* kfifo */
778 spin_lock_init(&fujitsu_laptop->fifo_lock);
779 error = kfifo_alloc(&fujitsu_laptop->fifo, RINGBUFFERSIZE * sizeof(int),
780 GFP_KERNEL);
781 if (error) {
782 pr_err("kfifo_alloc failed\n");
783 goto err_stop;
784 }
785
786 error = acpi_fujitsu_laptop_input_setup(device);
787 if (error)
788 goto err_free_fifo;
789
790 error = acpi_bus_update_power(fujitsu_laptop->acpi_handle, &state);
791 if (error) {
792 pr_err("Error reading power state\n");
793 goto err_free_fifo;
794 }
795
796 pr_info("ACPI: %s [%s] (%s)\n",
797 acpi_device_name(device), acpi_device_bid(device),
798 !device->power.state ? "on" : "off");
799
800 fujitsu_laptop->dev = device;
801
802 if (acpi_has_method(device->handle, METHOD_NAME__INI)) {
803 vdbg_printk(FUJLAPTOP_DBG_INFO, "Invoking _INI\n");
804 if (ACPI_FAILURE
805 (acpi_evaluate_object
806 (device->handle, METHOD_NAME__INI, NULL, NULL)))
807 pr_err("_INI Method failed\n");
808 }
809
810 i = 0;
811 while (call_fext_func(FUNC_BUTTONS, 0x1, 0x0, 0x0) != 0
812 && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE)
813 ; /* No action, result is discarded */
814 vdbg_printk(FUJLAPTOP_DBG_INFO, "Discarded %i ringbuffer entries\n", i);
815
816 fujitsu_laptop->flags_supported =
817 call_fext_func(FUNC_FLAGS, 0x0, 0x0, 0x0);
818
819 /* Make sure our bitmask of supported functions is cleared if the
820 RFKILL function block is not implemented, like on the S7020. */
821 if (fujitsu_laptop->flags_supported == UNSUPPORTED_CMD)
822 fujitsu_laptop->flags_supported = 0;
823
824 if (fujitsu_laptop->flags_supported)
825 fujitsu_laptop->flags_state =
826 call_fext_func(FUNC_FLAGS, 0x4, 0x0, 0x0);
827
828 /* Suspect this is a keymap of the application panel, print it */
829 pr_info("BTNI: [0x%x]\n", call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0));
830
831 /* Sync backlight power status */
832 if (fujitsu_bl->bl_device &&
833 acpi_video_get_backlight_type() == acpi_backlight_vendor) {
834 if (call_fext_func(FUNC_BACKLIGHT, 0x2, 0x4, 0x0) == 3)
835 fujitsu_bl->bl_device->props.power = FB_BLANK_POWERDOWN;
836 else
837 fujitsu_bl->bl_device->props.power = FB_BLANK_UNBLANK;
838 }
839
840 error = fujitsu_laptop_platform_add();
841 if (error)
842 goto err_free_fifo;
843
844 #if IS_ENABLED(CONFIG_LEDS_CLASS)
845 if (call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & LOGOLAMP_POWERON) {
846 result = led_classdev_register(&fujitsu_laptop->pf_device->dev,
847 &logolamp_led);
848 if (result == 0) {
849 fujitsu_laptop->logolamp_registered = 1;
850 } else {
851 pr_err("Could not register LED handler for logo lamp, error %i\n",
852 result);
853 }
854 }
855
856 if ((call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & KEYBOARD_LAMPS) &&
857 (call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0) == 0x0)) {
858 result = led_classdev_register(&fujitsu_laptop->pf_device->dev,
859 &kblamps_led);
860 if (result == 0) {
861 fujitsu_laptop->kblamps_registered = 1;
862 } else {
863 pr_err("Could not register LED handler for keyboard lamps, error %i\n",
864 result);
865 }
866 }
867
868 /*
869 * BTNI bit 24 seems to indicate the presence of a radio toggle
870 * button in place of a slide switch, and all such machines appear
871 * to also have an RF LED. Therefore use bit 24 as an indicator
872 * that an RF LED is present.
873 */
874 if (call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0) & BIT(24)) {
875 result = led_classdev_register(&fujitsu_laptop->pf_device->dev,
876 &radio_led);
877 if (result == 0) {
878 fujitsu_laptop->radio_led_registered = 1;
879 } else {
880 pr_err("Could not register LED handler for radio LED, error %i\n",
881 result);
882 }
883 }
884
885 /* Support for eco led is not always signaled in bit corresponding
886 * to the bit used to control the led. According to the DSDT table,
887 * bit 14 seems to indicate presence of said led as well.
888 * Confirm by testing the status.
889 */
890 if ((call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & BIT(14)) &&
891 (call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0) != UNSUPPORTED_CMD)) {
892 result = led_classdev_register(&fujitsu_laptop->pf_device->dev,
893 &eco_led);
894 if (result == 0) {
895 fujitsu_laptop->eco_led_registered = 1;
896 } else {
897 pr_err("Could not register LED handler for eco LED, error %i\n",
898 result);
899 }
900 }
901 #endif
902
903 return result;
904
905 err_free_fifo:
906 kfifo_free(&fujitsu_laptop->fifo);
907 err_stop:
908 return error;
909 }
910
911 static int acpi_fujitsu_laptop_remove(struct acpi_device *device)
912 {
913 struct fujitsu_laptop *fujitsu_laptop = acpi_driver_data(device);
914
915 #if IS_ENABLED(CONFIG_LEDS_CLASS)
916 if (fujitsu_laptop->logolamp_registered)
917 led_classdev_unregister(&logolamp_led);
918
919 if (fujitsu_laptop->kblamps_registered)
920 led_classdev_unregister(&kblamps_led);
921
922 if (fujitsu_laptop->radio_led_registered)
923 led_classdev_unregister(&radio_led);
924
925 if (fujitsu_laptop->eco_led_registered)
926 led_classdev_unregister(&eco_led);
927 #endif
928
929 fujitsu_laptop_platform_remove();
930
931 kfifo_free(&fujitsu_laptop->fifo);
932
933 fujitsu_laptop->acpi_handle = NULL;
934
935 return 0;
936 }
937
938 static void acpi_fujitsu_laptop_press(int scancode)
939 {
940 struct input_dev *input = fujitsu_laptop->input;
941 int status;
942
943 status = kfifo_in_locked(&fujitsu_laptop->fifo,
944 (unsigned char *)&scancode, sizeof(scancode),
945 &fujitsu_laptop->fifo_lock);
946 if (status != sizeof(scancode)) {
947 vdbg_printk(FUJLAPTOP_DBG_WARN,
948 "Could not push scancode [0x%x]\n", scancode);
949 return;
950 }
951 sparse_keymap_report_event(input, scancode, 1, false);
952 vdbg_printk(FUJLAPTOP_DBG_TRACE,
953 "Push scancode into ringbuffer [0x%x]\n", scancode);
954 }
955
956 static void acpi_fujitsu_laptop_release(void)
957 {
958 struct input_dev *input = fujitsu_laptop->input;
959 int scancode, status;
960
961 while (true) {
962 status = kfifo_out_locked(&fujitsu_laptop->fifo,
963 (unsigned char *)&scancode,
964 sizeof(scancode),
965 &fujitsu_laptop->fifo_lock);
966 if (status != sizeof(scancode))
967 return;
968 sparse_keymap_report_event(input, scancode, 0, false);
969 vdbg_printk(FUJLAPTOP_DBG_TRACE,
970 "Pop scancode from ringbuffer [0x%x]\n", scancode);
971 }
972 }
973
974 static void acpi_fujitsu_laptop_notify(struct acpi_device *device, u32 event)
975 {
976 struct input_dev *input;
977 int scancode, i = 0;
978 unsigned int irb;
979
980 input = fujitsu_laptop->input;
981
982 if (event != ACPI_FUJITSU_NOTIFY_CODE1) {
983 vdbg_printk(FUJLAPTOP_DBG_WARN,
984 "Unsupported event [0x%x]\n", event);
985 sparse_keymap_report_event(input, -1, 1, true);
986 return;
987 }
988
989 if (fujitsu_laptop->flags_supported)
990 fujitsu_laptop->flags_state =
991 call_fext_func(FUNC_FLAGS, 0x4, 0x0, 0x0);
992
993 while ((irb = call_fext_func(FUNC_BUTTONS, 0x1, 0x0, 0x0)) != 0 &&
994 i++ < MAX_HOTKEY_RINGBUFFER_SIZE) {
995 scancode = irb & 0x4ff;
996 if (sparse_keymap_entry_from_scancode(input, scancode))
997 acpi_fujitsu_laptop_press(scancode);
998 else if (scancode == 0)
999 acpi_fujitsu_laptop_release();
1000 else
1001 vdbg_printk(FUJLAPTOP_DBG_WARN,
1002 "Unknown GIRB result [%x]\n", irb);
1003 }
1004
1005 /* On some models (first seen on the Skylake-based Lifebook
1006 * E736/E746/E756), the touchpad toggle hotkey (Fn+F4) is
1007 * handled in software; its state is queried using FUNC_FLAGS
1008 */
1009 if ((fujitsu_laptop->flags_supported & BIT(26)) &&
1010 (call_fext_func(FUNC_FLAGS, 0x1, 0x0, 0x0) & BIT(26)))
1011 sparse_keymap_report_event(input, BIT(26), 1, true);
1012 }
1013
1014 /* Initialization */
1015
1016 static const struct acpi_device_id fujitsu_bl_device_ids[] = {
1017 {ACPI_FUJITSU_BL_HID, 0},
1018 {"", 0},
1019 };
1020
1021 static struct acpi_driver acpi_fujitsu_bl_driver = {
1022 .name = ACPI_FUJITSU_BL_DRIVER_NAME,
1023 .class = ACPI_FUJITSU_CLASS,
1024 .ids = fujitsu_bl_device_ids,
1025 .ops = {
1026 .add = acpi_fujitsu_bl_add,
1027 .notify = acpi_fujitsu_bl_notify,
1028 },
1029 };
1030
1031 static const struct acpi_device_id fujitsu_laptop_device_ids[] = {
1032 {ACPI_FUJITSU_LAPTOP_HID, 0},
1033 {"", 0},
1034 };
1035
1036 static struct acpi_driver acpi_fujitsu_laptop_driver = {
1037 .name = ACPI_FUJITSU_LAPTOP_DRIVER_NAME,
1038 .class = ACPI_FUJITSU_CLASS,
1039 .ids = fujitsu_laptop_device_ids,
1040 .ops = {
1041 .add = acpi_fujitsu_laptop_add,
1042 .remove = acpi_fujitsu_laptop_remove,
1043 .notify = acpi_fujitsu_laptop_notify,
1044 },
1045 };
1046
1047 static const struct acpi_device_id fujitsu_ids[] __used = {
1048 {ACPI_FUJITSU_BL_HID, 0},
1049 {ACPI_FUJITSU_LAPTOP_HID, 0},
1050 {"", 0}
1051 };
1052 MODULE_DEVICE_TABLE(acpi, fujitsu_ids);
1053
1054 static int __init fujitsu_init(void)
1055 {
1056 int ret;
1057
1058 if (acpi_disabled)
1059 return -ENODEV;
1060
1061 fujitsu_bl = kzalloc(sizeof(struct fujitsu_bl), GFP_KERNEL);
1062 if (!fujitsu_bl)
1063 return -ENOMEM;
1064
1065 ret = acpi_bus_register_driver(&acpi_fujitsu_bl_driver);
1066 if (ret)
1067 goto err_free_fujitsu_bl;
1068
1069 /* Register platform stuff */
1070
1071 ret = platform_driver_register(&fujitsu_pf_driver);
1072 if (ret)
1073 goto err_unregister_acpi;
1074
1075 /* Register laptop driver */
1076
1077 fujitsu_laptop = kzalloc(sizeof(struct fujitsu_laptop), GFP_KERNEL);
1078 if (!fujitsu_laptop) {
1079 ret = -ENOMEM;
1080 goto err_unregister_platform_driver;
1081 }
1082
1083 ret = acpi_bus_register_driver(&acpi_fujitsu_laptop_driver);
1084 if (ret)
1085 goto err_free_fujitsu_laptop;
1086
1087 pr_info("driver " FUJITSU_DRIVER_VERSION " successfully loaded\n");
1088
1089 return 0;
1090
1091 err_free_fujitsu_laptop:
1092 kfree(fujitsu_laptop);
1093 err_unregister_platform_driver:
1094 platform_driver_unregister(&fujitsu_pf_driver);
1095 err_unregister_acpi:
1096 acpi_bus_unregister_driver(&acpi_fujitsu_bl_driver);
1097 err_free_fujitsu_bl:
1098 kfree(fujitsu_bl);
1099
1100 return ret;
1101 }
1102
1103 static void __exit fujitsu_cleanup(void)
1104 {
1105 acpi_bus_unregister_driver(&acpi_fujitsu_laptop_driver);
1106
1107 kfree(fujitsu_laptop);
1108
1109 platform_driver_unregister(&fujitsu_pf_driver);
1110
1111 acpi_bus_unregister_driver(&acpi_fujitsu_bl_driver);
1112
1113 kfree(fujitsu_bl);
1114
1115 pr_info("driver unloaded\n");
1116 }
1117
1118 module_init(fujitsu_init);
1119 module_exit(fujitsu_cleanup);
1120
1121 module_param(use_alt_lcd_levels, int, 0644);
1122 MODULE_PARM_DESC(use_alt_lcd_levels, "Interface used for setting LCD brightness level (-1 = auto, 0 = force SBLL, 1 = force SBL2)");
1123 module_param(disable_brightness_adjust, bool, 0644);
1124 MODULE_PARM_DESC(disable_brightness_adjust, "Disable LCD brightness adjustment");
1125 #ifdef CONFIG_FUJITSU_LAPTOP_DEBUG
1126 module_param_named(debug, dbg_level, uint, 0644);
1127 MODULE_PARM_DESC(debug, "Sets debug level bit-mask");
1128 #endif
1129
1130 MODULE_AUTHOR("Jonathan Woithe, Peter Gruber, Tony Vroon");
1131 MODULE_DESCRIPTION("Fujitsu laptop extras support");
1132 MODULE_VERSION(FUJITSU_DRIVER_VERSION);
1133 MODULE_LICENSE("GPL");