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