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