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