blob: 17a259eb3eed6e15c3291a84c6f7fdd6ca8ba130 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * toshiba_acpi.c - Toshiba Laptop ACPI Extras
3 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 * Copyright (C) 2002-2004 John Belmonte
philipl@overt.orgc41a40c2008-08-30 11:57:39 -04005 * Copyright (C) 2008 Philip Langdale
Pierre Ducroquet6c3f6e62010-07-29 11:56:59 +02006 * Copyright (C) 2010 Pierre Ducroquet
Azael Avalos7216d702015-02-10 21:09:21 -07007 * Copyright (C) 2014-2015 Azael Avalos
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
Darren Hartc57c0fa2015-02-11 21:25:22 -080019 * The full GNU General Public License is included in this distribution in
20 * the file called "COPYING".
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 *
22 * The devolpment page for this driver is located at
23 * http://memebeam.org/toys/ToshibaAcpiDriver.
24 *
25 * Credits:
26 * Jonathan A. Buzzard - Toshiba HCI info, and critical tips on reverse
27 * engineering the Windows drivers
28 * Yasushi Nagato - changes for linux kernel 2.4 -> 2.5
29 * Rob Miller - TV out and hotkeys help
Linus Torvalds1da177e2005-04-16 15:20:36 -070030 */
31
Joe Perches7e334602011-03-29 15:21:52 -070032#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
33
Azael Avalos7216d702015-02-10 21:09:21 -070034#define TOSHIBA_ACPI_VERSION "0.21"
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#define PROC_INTERFACE_VERSION 1
36
37#include <linux/kernel.h>
38#include <linux/module.h>
39#include <linux/init.h>
40#include <linux/types.h>
41#include <linux/proc_fs.h>
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -080042#include <linux/seq_file.h>
Holger Machtc9263552006-10-20 14:30:29 -070043#include <linux/backlight.h>
philipl@overt.orgc41a40c2008-08-30 11:57:39 -040044#include <linux/rfkill.h>
Matthew Garrett6335e4d2010-02-25 15:20:54 -050045#include <linux/input.h>
Dmitry Torokhov384a7cd2010-08-04 22:30:19 -070046#include <linux/input/sparse-keymap.h>
Pierre Ducroquet6c3f6e62010-07-29 11:56:59 +020047#include <linux/leds.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090048#include <linux/slab.h>
Seth Forshee29cd2932012-01-18 13:44:09 -060049#include <linux/workqueue.h>
50#include <linux/i8042.h>
Lv Zheng8b484632013-12-03 08:49:16 +080051#include <linux/acpi.h>
Azael Avalosb5163992015-02-10 23:43:56 -070052#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
Linus Torvalds1da177e2005-04-16 15:20:36 -070054MODULE_AUTHOR("John Belmonte");
55MODULE_DESCRIPTION("Toshiba Laptop ACPI Extras Driver");
56MODULE_LICENSE("GPL");
57
Seth Forsheef11f9992012-01-18 13:44:11 -060058#define TOSHIBA_WMI_EVENT_GUID "59142400-C6A3-40FA-BADB-8A2652834100"
59
Seth Forshee29cd2932012-01-18 13:44:09 -060060/* Scan code for Fn key on TOS1900 models */
61#define TOS1900_FN_SCAN 0x6e
62
Linus Torvalds1da177e2005-04-16 15:20:36 -070063/* Toshiba ACPI method paths */
Linus Torvalds1da177e2005-04-16 15:20:36 -070064#define METHOD_VIDEO_OUT "\\_SB_.VALX.DSSX"
65
Darren Harte0769fe2015-02-11 20:50:08 -080066/*
67 * The Toshiba configuration interface is composed of the HCI and the SCI,
Azael Avalos258c5902014-09-29 20:40:07 -060068 * which are defined as follows:
Linus Torvalds1da177e2005-04-16 15:20:36 -070069 *
70 * HCI is Toshiba's "Hardware Control Interface" which is supposed to
71 * be uniform across all their models. Ideally we would just call
72 * dedicated ACPI methods instead of using this primitive interface.
73 * However the ACPI methods seem to be incomplete in some areas (for
74 * example they allow setting, but not reading, the LCD brightness value),
75 * so this is still useful.
Matthew Garrettea6b31f2014-04-04 14:22:34 -040076 *
Azael Avalos84a62732014-03-25 20:38:29 -060077 * SCI stands for "System Configuration Interface" which aim is to
78 * conceal differences in hardware between different models.
Linus Torvalds1da177e2005-04-16 15:20:36 -070079 */
80
Azael Avalos258c5902014-09-29 20:40:07 -060081#define TCI_WORDS 6
Linus Torvalds1da177e2005-04-16 15:20:36 -070082
83/* operations */
84#define HCI_SET 0xff00
85#define HCI_GET 0xfe00
Azael Avalos84a62732014-03-25 20:38:29 -060086#define SCI_OPEN 0xf100
87#define SCI_CLOSE 0xf200
88#define SCI_GET 0xf300
89#define SCI_SET 0xf400
Linus Torvalds1da177e2005-04-16 15:20:36 -070090
91/* return codes */
Azael Avalos1864bbc2014-09-29 20:40:08 -060092#define TOS_SUCCESS 0x0000
93#define TOS_OPEN_CLOSE_OK 0x0044
94#define TOS_FAILURE 0x1000
95#define TOS_NOT_SUPPORTED 0x8000
96#define TOS_ALREADY_OPEN 0x8100
97#define TOS_NOT_OPENED 0x8200
98#define TOS_INPUT_DATA_ERROR 0x8300
99#define TOS_WRITE_PROTECTED 0x8400
100#define TOS_NOT_PRESENT 0x8600
101#define TOS_FIFO_EMPTY 0x8c00
102#define TOS_DATA_NOT_AVAILABLE 0x8d20
103#define TOS_NOT_INITIALIZED 0x8d50
Azael Avalos98fc4ec2015-02-09 20:55:02 -0700104#define TOS_NOT_INSTALLED 0x8e00
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105
106/* registers */
107#define HCI_FAN 0x0004
Akio Idehara121b7b02012-04-06 01:46:43 +0900108#define HCI_TR_BACKLIGHT 0x0005
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109#define HCI_SYSTEM_EVENT 0x0016
110#define HCI_VIDEO_OUT 0x001c
111#define HCI_HOTKEY_EVENT 0x001e
112#define HCI_LCD_BRIGHTNESS 0x002a
philipl@overt.orgc41a40c2008-08-30 11:57:39 -0400113#define HCI_WIRELESS 0x0056
Azael Avalos5a2813e2014-03-25 20:38:34 -0600114#define HCI_ACCELEROMETER 0x006d
Azael Avalos360f0f32014-03-25 20:38:31 -0600115#define HCI_KBD_ILLUMINATION 0x0095
Azael Avalosdef6c4e2014-03-25 20:38:33 -0600116#define HCI_ECO_MODE 0x0097
Azael Avalos5a2813e2014-03-25 20:38:34 -0600117#define HCI_ACCELEROMETER2 0x00a6
Azael Avalos56e6b352015-03-20 16:55:16 -0600118#define HCI_SYSTEM_INFO 0xc000
Azael Avalos35d53ce2015-02-10 21:09:19 -0700119#define SCI_PANEL_POWER_ON 0x010d
Azael Avalosfdb79082014-03-25 20:38:30 -0600120#define SCI_ILLUMINATION 0x014e
Azael Avalose26ffe52015-01-18 18:30:22 -0700121#define SCI_USB_SLEEP_CHARGE 0x0150
Azael Avalos360f0f32014-03-25 20:38:31 -0600122#define SCI_KBD_ILLUM_STATUS 0x015c
Azael Avalos172ce0a2015-01-18 18:30:25 -0700123#define SCI_USB_SLEEP_MUSIC 0x015e
Azael Avalos17fe4b32015-02-10 21:09:20 -0700124#define SCI_USB_THREE 0x0169
Azael Avalos9d8658a2014-03-25 20:38:32 -0600125#define SCI_TOUCHPAD 0x050e
Azael Avalosbae84192015-02-10 21:09:18 -0700126#define SCI_KBD_FUNCTION_KEYS 0x0522
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127
128/* field definitions */
Azael Avalos5a2813e2014-03-25 20:38:34 -0600129#define HCI_ACCEL_MASK 0x7fff
Seth Forshee29cd2932012-01-18 13:44:09 -0600130#define HCI_HOTKEY_DISABLE 0x0b
131#define HCI_HOTKEY_ENABLE 0x09
Azael Avalosfb42d1f2015-03-20 16:55:18 -0600132#define HCI_HOTKEY_SPECIAL_FUNCTIONS 0x10
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133#define HCI_LCD_BRIGHTNESS_BITS 3
134#define HCI_LCD_BRIGHTNESS_SHIFT (16-HCI_LCD_BRIGHTNESS_BITS)
135#define HCI_LCD_BRIGHTNESS_LEVELS (1 << HCI_LCD_BRIGHTNESS_BITS)
Azael Avalos360f0f32014-03-25 20:38:31 -0600136#define HCI_MISC_SHIFT 0x10
Azael Avalos56e6b352015-03-20 16:55:16 -0600137#define HCI_SYSTEM_TYPE1 0x10
138#define HCI_SYSTEM_TYPE2 0x11
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139#define HCI_VIDEO_OUT_LCD 0x1
140#define HCI_VIDEO_OUT_CRT 0x2
141#define HCI_VIDEO_OUT_TV 0x4
philipl@overt.orgc41a40c2008-08-30 11:57:39 -0400142#define HCI_WIRELESS_KILL_SWITCH 0x01
143#define HCI_WIRELESS_BT_PRESENT 0x0f
144#define HCI_WIRELESS_BT_ATTACH 0x40
145#define HCI_WIRELESS_BT_POWER 0x80
Azael Avalos93f8c162014-09-12 18:50:36 -0600146#define SCI_KBD_MODE_MASK 0x1f
Azael Avalos360f0f32014-03-25 20:38:31 -0600147#define SCI_KBD_MODE_FNZ 0x1
148#define SCI_KBD_MODE_AUTO 0x2
Azael Avalos93f8c162014-09-12 18:50:36 -0600149#define SCI_KBD_MODE_ON 0x8
150#define SCI_KBD_MODE_OFF 0x10
151#define SCI_KBD_TIME_MAX 0x3c001a
Azael Avalose26ffe52015-01-18 18:30:22 -0700152#define SCI_USB_CHARGE_MODE_MASK 0xff
153#define SCI_USB_CHARGE_DISABLED 0x30000
154#define SCI_USB_CHARGE_ALTERNATE 0x30009
155#define SCI_USB_CHARGE_AUTO 0x30021
Azael Avalos182bcaa2015-01-18 18:30:23 -0700156#define SCI_USB_CHARGE_BAT_MASK 0x7
157#define SCI_USB_CHARGE_BAT_LVL_OFF 0x1
158#define SCI_USB_CHARGE_BAT_LVL_ON 0x4
159#define SCI_USB_CHARGE_BAT_LVL 0x0200
Azael Avalosbb3fe012015-01-18 18:30:24 -0700160#define SCI_USB_CHARGE_RAPID_DSP 0x0300
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161
Seth Forshee135740d2011-09-20 16:55:49 -0500162struct toshiba_acpi_dev {
163 struct acpi_device *acpi_dev;
164 const char *method_hci;
165 struct rfkill *bt_rfk;
166 struct input_dev *hotkey_dev;
Seth Forshee29cd2932012-01-18 13:44:09 -0600167 struct work_struct hotkey_work;
Seth Forshee135740d2011-09-20 16:55:49 -0500168 struct backlight_device *backlight_dev;
169 struct led_classdev led_dev;
Azael Avalos360f0f32014-03-25 20:38:31 -0600170 struct led_classdev kbd_led;
Azael Avalosdef6c4e2014-03-25 20:38:33 -0600171 struct led_classdev eco_led;
Seth Forshee36d03f92011-09-20 16:55:53 -0500172
Seth Forshee135740d2011-09-20 16:55:49 -0500173 int force_fan;
174 int last_key_event;
175 int key_event_valid;
Azael Avalos93f8c162014-09-12 18:50:36 -0600176 int kbd_type;
Azael Avalos360f0f32014-03-25 20:38:31 -0600177 int kbd_mode;
178 int kbd_time;
Azael Avalos182bcaa2015-01-18 18:30:23 -0700179 int usbsc_bat_level;
Azael Avalosa2b34712015-03-20 16:55:17 -0600180 int hotkey_event_type;
Seth Forshee135740d2011-09-20 16:55:49 -0500181
Dan Carpenter592b7462012-01-15 14:28:20 +0300182 unsigned int illumination_supported:1;
183 unsigned int video_supported:1;
184 unsigned int fan_supported:1;
185 unsigned int system_event_supported:1;
Seth Forshee29cd2932012-01-18 13:44:09 -0600186 unsigned int ntfy_supported:1;
187 unsigned int info_supported:1;
Akio Idehara121b7b02012-04-06 01:46:43 +0900188 unsigned int tr_backlight_supported:1;
Azael Avalos360f0f32014-03-25 20:38:31 -0600189 unsigned int kbd_illum_supported:1;
190 unsigned int kbd_led_registered:1;
Azael Avalos9d8658a2014-03-25 20:38:32 -0600191 unsigned int touchpad_supported:1;
Azael Avalosdef6c4e2014-03-25 20:38:33 -0600192 unsigned int eco_supported:1;
Azael Avalos5a2813e2014-03-25 20:38:34 -0600193 unsigned int accelerometer_supported:1;
Azael Avalose26ffe52015-01-18 18:30:22 -0700194 unsigned int usb_sleep_charge_supported:1;
Azael Avalosbb3fe012015-01-18 18:30:24 -0700195 unsigned int usb_rapid_charge_supported:1;
Azael Avalos172ce0a2015-01-18 18:30:25 -0700196 unsigned int usb_sleep_music_supported:1;
Azael Avalosbae84192015-02-10 21:09:18 -0700197 unsigned int kbd_function_keys_supported:1;
Azael Avalos35d53ce2015-02-10 21:09:19 -0700198 unsigned int panel_power_on_supported:1;
Azael Avalos17fe4b32015-02-10 21:09:20 -0700199 unsigned int usb_three_supported:1;
Azael Avalos360f0f32014-03-25 20:38:31 -0600200 unsigned int sysfs_created:1;
Seth Forshee36d03f92011-09-20 16:55:53 -0500201
Seth Forshee135740d2011-09-20 16:55:49 -0500202 struct mutex mutex;
203};
204
Seth Forshee29cd2932012-01-18 13:44:09 -0600205static struct toshiba_acpi_dev *toshiba_acpi;
206
arvidjaar@mail.ru4db42c52008-03-04 15:06:34 -0800207static const struct acpi_device_id toshiba_device_ids[] = {
208 {"TOS6200", 0},
Ondrej Zary63a9e012014-11-10 00:11:54 +0100209 {"TOS6207", 0},
philipl@overt.orgc41a40c2008-08-30 11:57:39 -0400210 {"TOS6208", 0},
arvidjaar@mail.ru4db42c52008-03-04 15:06:34 -0800211 {"TOS1900", 0},
212 {"", 0},
213};
214MODULE_DEVICE_TABLE(acpi, toshiba_device_ids);
215
Greg Kroah-Hartmanb859f152012-12-21 13:18:33 -0800216static const struct key_entry toshiba_acpi_keymap[] = {
Unai Uribarrifec278a2014-01-14 11:06:47 +0100217 { KE_KEY, 0x9e, { KEY_RFKILL } },
Dmitry Torokhov384a7cd2010-08-04 22:30:19 -0700218 { KE_KEY, 0x101, { KEY_MUTE } },
219 { KE_KEY, 0x102, { KEY_ZOOMOUT } },
220 { KE_KEY, 0x103, { KEY_ZOOMIN } },
Azael Avalos408a5d12014-09-05 11:14:03 -0600221 { KE_KEY, 0x10f, { KEY_TAB } },
Azael Avalosaf502832012-01-18 13:44:10 -0600222 { KE_KEY, 0x12c, { KEY_KBDILLUMTOGGLE } },
223 { KE_KEY, 0x139, { KEY_ZOOMRESET } },
Dmitry Torokhov384a7cd2010-08-04 22:30:19 -0700224 { KE_KEY, 0x13b, { KEY_COFFEE } },
225 { KE_KEY, 0x13c, { KEY_BATTERY } },
226 { KE_KEY, 0x13d, { KEY_SLEEP } },
227 { KE_KEY, 0x13e, { KEY_SUSPEND } },
228 { KE_KEY, 0x13f, { KEY_SWITCHVIDEOMODE } },
229 { KE_KEY, 0x140, { KEY_BRIGHTNESSDOWN } },
230 { KE_KEY, 0x141, { KEY_BRIGHTNESSUP } },
231 { KE_KEY, 0x142, { KEY_WLAN } },
Azael Avalosaf502832012-01-18 13:44:10 -0600232 { KE_KEY, 0x143, { KEY_TOUCHPAD_TOGGLE } },
Jon Dowlanda49010f2010-10-27 00:24:59 +0100233 { KE_KEY, 0x17f, { KEY_FN } },
Dmitry Torokhov384a7cd2010-08-04 22:30:19 -0700234 { KE_KEY, 0xb05, { KEY_PROG2 } },
235 { KE_KEY, 0xb06, { KEY_WWW } },
236 { KE_KEY, 0xb07, { KEY_MAIL } },
237 { KE_KEY, 0xb30, { KEY_STOP } },
238 { KE_KEY, 0xb31, { KEY_PREVIOUSSONG } },
239 { KE_KEY, 0xb32, { KEY_NEXTSONG } },
240 { KE_KEY, 0xb33, { KEY_PLAYPAUSE } },
241 { KE_KEY, 0xb5a, { KEY_MEDIA } },
Azael Avalos408a5d12014-09-05 11:14:03 -0600242 { KE_IGNORE, 0x1430, { KEY_RESERVED } }, /* Wake from sleep */
243 { KE_IGNORE, 0x1501, { KEY_RESERVED } }, /* Output changed */
244 { KE_IGNORE, 0x1502, { KEY_RESERVED } }, /* HDMI plugged/unplugged */
245 { KE_IGNORE, 0x1ABE, { KEY_RESERVED } }, /* Protection level set */
246 { KE_IGNORE, 0x1ABF, { KEY_RESERVED } }, /* Protection level off */
Dmitry Torokhov384a7cd2010-08-04 22:30:19 -0700247 { KE_END, 0 },
Matthew Garrett6335e4d2010-02-25 15:20:54 -0500248};
249
Takashi Iwaife808bfb2014-04-29 15:15:38 +0200250static const struct key_entry toshiba_acpi_alt_keymap[] = {
251 { KE_KEY, 0x157, { KEY_MUTE } },
252 { KE_KEY, 0x102, { KEY_ZOOMOUT } },
253 { KE_KEY, 0x103, { KEY_ZOOMIN } },
Azael Avalose6efad72014-08-04 09:21:02 -0600254 { KE_KEY, 0x12c, { KEY_KBDILLUMTOGGLE } },
Takashi Iwaife808bfb2014-04-29 15:15:38 +0200255 { KE_KEY, 0x139, { KEY_ZOOMRESET } },
256 { KE_KEY, 0x13e, { KEY_SWITCHVIDEOMODE } },
257 { KE_KEY, 0x13c, { KEY_BRIGHTNESSDOWN } },
258 { KE_KEY, 0x13d, { KEY_BRIGHTNESSUP } },
259 { KE_KEY, 0x158, { KEY_WLAN } },
260 { KE_KEY, 0x13f, { KEY_TOUCHPAD_TOGGLE } },
261 { KE_END, 0 },
262};
263
Darren Harte0769fe2015-02-11 20:50:08 -0800264/*
265 * Utility
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 */
267
Azael Avalosb5163992015-02-10 23:43:56 -0700268static inline void _set_bit(u32 *word, u32 mask, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269{
270 *word = (*word & ~mask) | (mask * value);
271}
272
Darren Harte0769fe2015-02-11 20:50:08 -0800273/*
274 * ACPI interface wrappers
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 */
276
Len Brown4be44fc2005-08-05 00:44:28 -0400277static int write_acpi_int(const char *methodName, int val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 acpi_status status;
280
Zhang Rui619400d2013-09-03 08:31:56 +0800281 status = acpi_execute_simple_method(NULL, (char *)methodName, val);
Seth Forshee32bcd5c2011-09-20 16:55:50 -0500282 return (status == AE_OK) ? 0 : -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283}
284
Darren Harte0769fe2015-02-11 20:50:08 -0800285/*
286 * Perform a raw configuration call. Here we don't care about input or output
Azael Avalos258c5902014-09-29 20:40:07 -0600287 * buffer format.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 */
Azael Avalos258c5902014-09-29 20:40:07 -0600289static acpi_status tci_raw(struct toshiba_acpi_dev *dev,
290 const u32 in[TCI_WORDS], u32 out[TCI_WORDS])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291{
292 struct acpi_object_list params;
Azael Avalos258c5902014-09-29 20:40:07 -0600293 union acpi_object in_objs[TCI_WORDS];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 struct acpi_buffer results;
Azael Avalos258c5902014-09-29 20:40:07 -0600295 union acpi_object out_objs[TCI_WORDS + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 acpi_status status;
297 int i;
298
Azael Avalos258c5902014-09-29 20:40:07 -0600299 params.count = TCI_WORDS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 params.pointer = in_objs;
Azael Avalos258c5902014-09-29 20:40:07 -0600301 for (i = 0; i < TCI_WORDS; ++i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 in_objs[i].type = ACPI_TYPE_INTEGER;
303 in_objs[i].integer.value = in[i];
304 }
305
306 results.length = sizeof(out_objs);
307 results.pointer = out_objs;
308
Seth Forshee6e02cc72011-09-20 16:55:51 -0500309 status = acpi_evaluate_object(dev->acpi_dev->handle,
310 (char *)dev->method_hci, &params,
Len Brown4be44fc2005-08-05 00:44:28 -0400311 &results);
Azael Avalos258c5902014-09-29 20:40:07 -0600312 if ((status == AE_OK) && (out_objs->package.count <= TCI_WORDS)) {
Azael Avalosb5163992015-02-10 23:43:56 -0700313 for (i = 0; i < out_objs->package.count; ++i)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 out[i] = out_objs->package.elements[i].integer.value;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 }
316
317 return status;
318}
319
Darren Harte0769fe2015-02-11 20:50:08 -0800320/*
321 * Common hci tasks (get or set one or two value)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 *
323 * In addition to the ACPI status, the HCI system returns a result which
324 * may be useful (such as "not supported").
325 */
326
Azael Avalos893f3f62014-09-29 20:40:09 -0600327static u32 hci_write1(struct toshiba_acpi_dev *dev, u32 reg, u32 in1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328{
Azael Avalos258c5902014-09-29 20:40:07 -0600329 u32 in[TCI_WORDS] = { HCI_SET, reg, in1, 0, 0, 0 };
330 u32 out[TCI_WORDS];
331 acpi_status status = tci_raw(dev, in, out);
Azael Avalos893f3f62014-09-29 20:40:09 -0600332
333 return ACPI_SUCCESS(status) ? out[0] : TOS_FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334}
335
Azael Avalos893f3f62014-09-29 20:40:09 -0600336static u32 hci_read1(struct toshiba_acpi_dev *dev, u32 reg, u32 *out1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337{
Azael Avalos258c5902014-09-29 20:40:07 -0600338 u32 in[TCI_WORDS] = { HCI_GET, reg, 0, 0, 0, 0 };
339 u32 out[TCI_WORDS];
340 acpi_status status = tci_raw(dev, in, out);
Azael Avalosb5163992015-02-10 23:43:56 -0700341
Azael Avalos893f3f62014-09-29 20:40:09 -0600342 if (ACPI_FAILURE(status))
343 return TOS_FAILURE;
344
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 *out1 = out[2];
Azael Avalos893f3f62014-09-29 20:40:09 -0600346
347 return out[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348}
349
Azael Avalos893f3f62014-09-29 20:40:09 -0600350static u32 hci_write2(struct toshiba_acpi_dev *dev, u32 reg, u32 in1, u32 in2)
philipl@overt.orgc41a40c2008-08-30 11:57:39 -0400351{
Azael Avalos258c5902014-09-29 20:40:07 -0600352 u32 in[TCI_WORDS] = { HCI_SET, reg, in1, in2, 0, 0 };
353 u32 out[TCI_WORDS];
354 acpi_status status = tci_raw(dev, in, out);
Azael Avalos893f3f62014-09-29 20:40:09 -0600355
356 return ACPI_SUCCESS(status) ? out[0] : TOS_FAILURE;
philipl@overt.orgc41a40c2008-08-30 11:57:39 -0400357}
358
Azael Avalosb5163992015-02-10 23:43:56 -0700359static u32 hci_read2(struct toshiba_acpi_dev *dev,
360 u32 reg, u32 *out1, u32 *out2)
philipl@overt.orgc41a40c2008-08-30 11:57:39 -0400361{
Azael Avalos258c5902014-09-29 20:40:07 -0600362 u32 in[TCI_WORDS] = { HCI_GET, reg, *out1, *out2, 0, 0 };
363 u32 out[TCI_WORDS];
364 acpi_status status = tci_raw(dev, in, out);
Azael Avalosb5163992015-02-10 23:43:56 -0700365
Azael Avalos893f3f62014-09-29 20:40:09 -0600366 if (ACPI_FAILURE(status))
367 return TOS_FAILURE;
368
philipl@overt.orgc41a40c2008-08-30 11:57:39 -0400369 *out1 = out[2];
370 *out2 = out[3];
Azael Avalos893f3f62014-09-29 20:40:09 -0600371
372 return out[0];
philipl@overt.orgc41a40c2008-08-30 11:57:39 -0400373}
374
Darren Harte0769fe2015-02-11 20:50:08 -0800375/*
376 * Common sci tasks
Azael Avalos84a62732014-03-25 20:38:29 -0600377 */
378
379static int sci_open(struct toshiba_acpi_dev *dev)
380{
Azael Avalos258c5902014-09-29 20:40:07 -0600381 u32 in[TCI_WORDS] = { SCI_OPEN, 0, 0, 0, 0, 0 };
382 u32 out[TCI_WORDS];
Azael Avalos84a62732014-03-25 20:38:29 -0600383 acpi_status status;
384
Azael Avalos258c5902014-09-29 20:40:07 -0600385 status = tci_raw(dev, in, out);
Azael Avalos1864bbc2014-09-29 20:40:08 -0600386 if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) {
Azael Avalos84a62732014-03-25 20:38:29 -0600387 pr_err("ACPI call to open SCI failed\n");
388 return 0;
389 }
390
Azael Avalos1864bbc2014-09-29 20:40:08 -0600391 if (out[0] == TOS_OPEN_CLOSE_OK) {
Azael Avalos84a62732014-03-25 20:38:29 -0600392 return 1;
Azael Avalos1864bbc2014-09-29 20:40:08 -0600393 } else if (out[0] == TOS_ALREADY_OPEN) {
Azael Avalos84a62732014-03-25 20:38:29 -0600394 pr_info("Toshiba SCI already opened\n");
395 return 1;
Azael Avalosfa465732015-01-18 19:17:12 -0700396 } else if (out[0] == TOS_NOT_SUPPORTED) {
Darren Harte0769fe2015-02-11 20:50:08 -0800397 /*
398 * Some BIOSes do not have the SCI open/close functions
Azael Avalosfa465732015-01-18 19:17:12 -0700399 * implemented and return 0x8000 (Not Supported), failing to
400 * register some supported features.
401 *
402 * Simply return 1 if we hit those affected laptops to make the
403 * supported features work.
404 *
405 * In the case that some laptops really do not support the SCI,
406 * all the SCI dependent functions check for TOS_NOT_SUPPORTED,
407 * and thus, not registering support for the queried feature.
408 */
409 return 1;
Azael Avalos1864bbc2014-09-29 20:40:08 -0600410 } else if (out[0] == TOS_NOT_PRESENT) {
Azael Avalos84a62732014-03-25 20:38:29 -0600411 pr_info("Toshiba SCI is not present\n");
412 }
413
414 return 0;
415}
416
417static void sci_close(struct toshiba_acpi_dev *dev)
418{
Azael Avalos258c5902014-09-29 20:40:07 -0600419 u32 in[TCI_WORDS] = { SCI_CLOSE, 0, 0, 0, 0, 0 };
420 u32 out[TCI_WORDS];
Azael Avalos84a62732014-03-25 20:38:29 -0600421 acpi_status status;
422
Azael Avalos258c5902014-09-29 20:40:07 -0600423 status = tci_raw(dev, in, out);
Azael Avalos1864bbc2014-09-29 20:40:08 -0600424 if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) {
Azael Avalos84a62732014-03-25 20:38:29 -0600425 pr_err("ACPI call to close SCI failed\n");
426 return;
427 }
428
Azael Avalos1864bbc2014-09-29 20:40:08 -0600429 if (out[0] == TOS_OPEN_CLOSE_OK)
Azael Avalos84a62732014-03-25 20:38:29 -0600430 return;
Azael Avalos1864bbc2014-09-29 20:40:08 -0600431 else if (out[0] == TOS_NOT_OPENED)
Azael Avalos84a62732014-03-25 20:38:29 -0600432 pr_info("Toshiba SCI not opened\n");
Azael Avalos1864bbc2014-09-29 20:40:08 -0600433 else if (out[0] == TOS_NOT_PRESENT)
Azael Avalos84a62732014-03-25 20:38:29 -0600434 pr_info("Toshiba SCI is not present\n");
435}
436
Azael Avalos893f3f62014-09-29 20:40:09 -0600437static u32 sci_read(struct toshiba_acpi_dev *dev, u32 reg, u32 *out1)
Azael Avalos84a62732014-03-25 20:38:29 -0600438{
Azael Avalos258c5902014-09-29 20:40:07 -0600439 u32 in[TCI_WORDS] = { SCI_GET, reg, 0, 0, 0, 0 };
440 u32 out[TCI_WORDS];
441 acpi_status status = tci_raw(dev, in, out);
Azael Avalosb5163992015-02-10 23:43:56 -0700442
Azael Avalos893f3f62014-09-29 20:40:09 -0600443 if (ACPI_FAILURE(status))
444 return TOS_FAILURE;
445
Azael Avalos84a62732014-03-25 20:38:29 -0600446 *out1 = out[2];
Azael Avalos893f3f62014-09-29 20:40:09 -0600447
448 return out[0];
Azael Avalos84a62732014-03-25 20:38:29 -0600449}
450
Azael Avalos893f3f62014-09-29 20:40:09 -0600451static u32 sci_write(struct toshiba_acpi_dev *dev, u32 reg, u32 in1)
Azael Avalos84a62732014-03-25 20:38:29 -0600452{
Azael Avalos258c5902014-09-29 20:40:07 -0600453 u32 in[TCI_WORDS] = { SCI_SET, reg, in1, 0, 0, 0 };
454 u32 out[TCI_WORDS];
455 acpi_status status = tci_raw(dev, in, out);
Azael Avalos893f3f62014-09-29 20:40:09 -0600456
457 return ACPI_SUCCESS(status) ? out[0] : TOS_FAILURE;
Azael Avalos84a62732014-03-25 20:38:29 -0600458}
459
Pierre Ducroquet6c3f6e62010-07-29 11:56:59 +0200460/* Illumination support */
Seth Forshee135740d2011-09-20 16:55:49 -0500461static int toshiba_illumination_available(struct toshiba_acpi_dev *dev)
Pierre Ducroquet6c3f6e62010-07-29 11:56:59 +0200462{
Azael Avalos258c5902014-09-29 20:40:07 -0600463 u32 in[TCI_WORDS] = { SCI_GET, SCI_ILLUMINATION, 0, 0, 0, 0 };
464 u32 out[TCI_WORDS];
Pierre Ducroquet6c3f6e62010-07-29 11:56:59 +0200465 acpi_status status;
466
Azael Avalosfdb79082014-03-25 20:38:30 -0600467 if (!sci_open(dev))
468 return 0;
469
Azael Avalos258c5902014-09-29 20:40:07 -0600470 status = tci_raw(dev, in, out);
Azael Avalosfdb79082014-03-25 20:38:30 -0600471 sci_close(dev);
Azael Avalos1864bbc2014-09-29 20:40:08 -0600472 if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) {
Azael Avalosfdb79082014-03-25 20:38:30 -0600473 pr_err("ACPI call to query Illumination support failed\n");
474 return 0;
Azael Avalos1864bbc2014-09-29 20:40:08 -0600475 } else if (out[0] == TOS_NOT_SUPPORTED) {
Joe Perches7e334602011-03-29 15:21:52 -0700476 pr_info("Illumination device not available\n");
Pierre Ducroquet6c3f6e62010-07-29 11:56:59 +0200477 return 0;
478 }
Azael Avalosfdb79082014-03-25 20:38:30 -0600479
Pierre Ducroquet6c3f6e62010-07-29 11:56:59 +0200480 return 1;
481}
482
483static void toshiba_illumination_set(struct led_classdev *cdev,
484 enum led_brightness brightness)
485{
Seth Forshee135740d2011-09-20 16:55:49 -0500486 struct toshiba_acpi_dev *dev = container_of(cdev,
487 struct toshiba_acpi_dev, led_dev);
Azael Avalosfdb79082014-03-25 20:38:30 -0600488 u32 state, result;
Pierre Ducroquet6c3f6e62010-07-29 11:56:59 +0200489
490 /* First request : initialize communication. */
Azael Avalosfdb79082014-03-25 20:38:30 -0600491 if (!sci_open(dev))
492 return;
493
494 /* Switch the illumination on/off */
495 state = brightness ? 1 : 0;
Azael Avalos893f3f62014-09-29 20:40:09 -0600496 result = sci_write(dev, SCI_ILLUMINATION, state);
Azael Avalosfdb79082014-03-25 20:38:30 -0600497 sci_close(dev);
Azael Avalos893f3f62014-09-29 20:40:09 -0600498 if (result == TOS_FAILURE) {
Azael Avalosfdb79082014-03-25 20:38:30 -0600499 pr_err("ACPI call for illumination failed\n");
500 return;
Azael Avalos1864bbc2014-09-29 20:40:08 -0600501 } else if (result == TOS_NOT_SUPPORTED) {
Azael Avalosfdb79082014-03-25 20:38:30 -0600502 pr_info("Illumination not supported\n");
Pierre Ducroquet6c3f6e62010-07-29 11:56:59 +0200503 return;
504 }
Pierre Ducroquet6c3f6e62010-07-29 11:56:59 +0200505}
506
507static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev)
508{
Seth Forshee135740d2011-09-20 16:55:49 -0500509 struct toshiba_acpi_dev *dev = container_of(cdev,
510 struct toshiba_acpi_dev, led_dev);
Azael Avalosfdb79082014-03-25 20:38:30 -0600511 u32 state, result;
Pierre Ducroquet6c3f6e62010-07-29 11:56:59 +0200512
513 /* First request : initialize communication. */
Azael Avalosfdb79082014-03-25 20:38:30 -0600514 if (!sci_open(dev))
Pierre Ducroquet6c3f6e62010-07-29 11:56:59 +0200515 return LED_OFF;
Pierre Ducroquet6c3f6e62010-07-29 11:56:59 +0200516
517 /* Check the illumination */
Azael Avalos893f3f62014-09-29 20:40:09 -0600518 result = sci_read(dev, SCI_ILLUMINATION, &state);
Azael Avalosfdb79082014-03-25 20:38:30 -0600519 sci_close(dev);
Azael Avalos893f3f62014-09-29 20:40:09 -0600520 if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) {
Azael Avalosfdb79082014-03-25 20:38:30 -0600521 pr_err("ACPI call for illumination failed\n");
522 return LED_OFF;
Azael Avalos1864bbc2014-09-29 20:40:08 -0600523 } else if (result == TOS_NOT_SUPPORTED) {
Azael Avalosfdb79082014-03-25 20:38:30 -0600524 pr_info("Illumination not supported\n");
Pierre Ducroquet6c3f6e62010-07-29 11:56:59 +0200525 return LED_OFF;
526 }
527
Azael Avalosfdb79082014-03-25 20:38:30 -0600528 return state ? LED_FULL : LED_OFF;
Pierre Ducroquet6c3f6e62010-07-29 11:56:59 +0200529}
Matthew Garrettea6b31f2014-04-04 14:22:34 -0400530
Azael Avalos360f0f32014-03-25 20:38:31 -0600531/* KBD Illumination */
Azael Avalos93f8c162014-09-12 18:50:36 -0600532static int toshiba_kbd_illum_available(struct toshiba_acpi_dev *dev)
533{
Azael Avalos258c5902014-09-29 20:40:07 -0600534 u32 in[TCI_WORDS] = { SCI_GET, SCI_KBD_ILLUM_STATUS, 0, 0, 0, 0 };
535 u32 out[TCI_WORDS];
Azael Avalos93f8c162014-09-12 18:50:36 -0600536 acpi_status status;
537
538 if (!sci_open(dev))
539 return 0;
540
Azael Avalos258c5902014-09-29 20:40:07 -0600541 status = tci_raw(dev, in, out);
Azael Avalos93f8c162014-09-12 18:50:36 -0600542 sci_close(dev);
Azael Avalos1864bbc2014-09-29 20:40:08 -0600543 if (ACPI_FAILURE(status) || out[0] == TOS_INPUT_DATA_ERROR) {
Azael Avalos93f8c162014-09-12 18:50:36 -0600544 pr_err("ACPI call to query kbd illumination support failed\n");
545 return 0;
Azael Avalos1864bbc2014-09-29 20:40:08 -0600546 } else if (out[0] == TOS_NOT_SUPPORTED) {
Azael Avalos93f8c162014-09-12 18:50:36 -0600547 pr_info("Keyboard illumination not available\n");
548 return 0;
549 }
550
Darren Harte0769fe2015-02-11 20:50:08 -0800551 /*
552 * Check for keyboard backlight timeout max value,
Azael Avalos93f8c162014-09-12 18:50:36 -0600553 * previous kbd backlight implementation set this to
554 * 0x3c0003, and now the new implementation set this
Darren Harte0769fe2015-02-11 20:50:08 -0800555 * to 0x3c001a, use this to distinguish between them.
Azael Avalos93f8c162014-09-12 18:50:36 -0600556 */
557 if (out[3] == SCI_KBD_TIME_MAX)
558 dev->kbd_type = 2;
559 else
560 dev->kbd_type = 1;
561 /* Get the current keyboard backlight mode */
562 dev->kbd_mode = out[2] & SCI_KBD_MODE_MASK;
563 /* Get the current time (1-60 seconds) */
564 dev->kbd_time = out[2] >> HCI_MISC_SHIFT;
565
566 return 1;
567}
568
Azael Avalos360f0f32014-03-25 20:38:31 -0600569static int toshiba_kbd_illum_status_set(struct toshiba_acpi_dev *dev, u32 time)
570{
571 u32 result;
Azael Avalos360f0f32014-03-25 20:38:31 -0600572
573 if (!sci_open(dev))
574 return -EIO;
575
Azael Avalos893f3f62014-09-29 20:40:09 -0600576 result = sci_write(dev, SCI_KBD_ILLUM_STATUS, time);
Azael Avalos360f0f32014-03-25 20:38:31 -0600577 sci_close(dev);
Azael Avalos893f3f62014-09-29 20:40:09 -0600578 if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) {
Azael Avalos360f0f32014-03-25 20:38:31 -0600579 pr_err("ACPI call to set KBD backlight status failed\n");
580 return -EIO;
Azael Avalos1864bbc2014-09-29 20:40:08 -0600581 } else if (result == TOS_NOT_SUPPORTED) {
Azael Avalos360f0f32014-03-25 20:38:31 -0600582 pr_info("Keyboard backlight status not supported\n");
583 return -ENODEV;
584 }
585
586 return 0;
587}
588
589static int toshiba_kbd_illum_status_get(struct toshiba_acpi_dev *dev, u32 *time)
590{
591 u32 result;
Azael Avalos360f0f32014-03-25 20:38:31 -0600592
593 if (!sci_open(dev))
594 return -EIO;
595
Azael Avalos893f3f62014-09-29 20:40:09 -0600596 result = sci_read(dev, SCI_KBD_ILLUM_STATUS, time);
Azael Avalos360f0f32014-03-25 20:38:31 -0600597 sci_close(dev);
Azael Avalos893f3f62014-09-29 20:40:09 -0600598 if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) {
Azael Avalos360f0f32014-03-25 20:38:31 -0600599 pr_err("ACPI call to get KBD backlight status failed\n");
600 return -EIO;
Azael Avalos1864bbc2014-09-29 20:40:08 -0600601 } else if (result == TOS_NOT_SUPPORTED) {
Azael Avalos360f0f32014-03-25 20:38:31 -0600602 pr_info("Keyboard backlight status not supported\n");
603 return -ENODEV;
604 }
605
606 return 0;
607}
608
609static enum led_brightness toshiba_kbd_backlight_get(struct led_classdev *cdev)
610{
611 struct toshiba_acpi_dev *dev = container_of(cdev,
612 struct toshiba_acpi_dev, kbd_led);
613 u32 state, result;
Azael Avalos360f0f32014-03-25 20:38:31 -0600614
615 /* Check the keyboard backlight state */
Azael Avalos893f3f62014-09-29 20:40:09 -0600616 result = hci_read1(dev, HCI_KBD_ILLUMINATION, &state);
617 if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) {
Azael Avalos360f0f32014-03-25 20:38:31 -0600618 pr_err("ACPI call to get the keyboard backlight failed\n");
619 return LED_OFF;
Azael Avalos1864bbc2014-09-29 20:40:08 -0600620 } else if (result == TOS_NOT_SUPPORTED) {
Azael Avalos360f0f32014-03-25 20:38:31 -0600621 pr_info("Keyboard backlight not supported\n");
622 return LED_OFF;
623 }
624
625 return state ? LED_FULL : LED_OFF;
626}
627
628static void toshiba_kbd_backlight_set(struct led_classdev *cdev,
629 enum led_brightness brightness)
630{
631 struct toshiba_acpi_dev *dev = container_of(cdev,
632 struct toshiba_acpi_dev, kbd_led);
633 u32 state, result;
Azael Avalos360f0f32014-03-25 20:38:31 -0600634
635 /* Set the keyboard backlight state */
636 state = brightness ? 1 : 0;
Azael Avalos893f3f62014-09-29 20:40:09 -0600637 result = hci_write1(dev, HCI_KBD_ILLUMINATION, state);
638 if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) {
Azael Avalos360f0f32014-03-25 20:38:31 -0600639 pr_err("ACPI call to set KBD Illumination mode failed\n");
640 return;
Azael Avalos1864bbc2014-09-29 20:40:08 -0600641 } else if (result == TOS_NOT_SUPPORTED) {
Azael Avalos360f0f32014-03-25 20:38:31 -0600642 pr_info("Keyboard backlight not supported\n");
643 return;
644 }
645}
Matthew Garrettea6b31f2014-04-04 14:22:34 -0400646
Azael Avalos9d8658a2014-03-25 20:38:32 -0600647/* TouchPad support */
648static int toshiba_touchpad_set(struct toshiba_acpi_dev *dev, u32 state)
649{
650 u32 result;
Azael Avalos9d8658a2014-03-25 20:38:32 -0600651
652 if (!sci_open(dev))
653 return -EIO;
654
Azael Avalos893f3f62014-09-29 20:40:09 -0600655 result = sci_write(dev, SCI_TOUCHPAD, state);
Azael Avalos9d8658a2014-03-25 20:38:32 -0600656 sci_close(dev);
Azael Avalos893f3f62014-09-29 20:40:09 -0600657 if (result == TOS_FAILURE) {
Azael Avalos9d8658a2014-03-25 20:38:32 -0600658 pr_err("ACPI call to set the touchpad failed\n");
659 return -EIO;
Azael Avalos1864bbc2014-09-29 20:40:08 -0600660 } else if (result == TOS_NOT_SUPPORTED) {
Azael Avalos9d8658a2014-03-25 20:38:32 -0600661 return -ENODEV;
662 }
663
664 return 0;
665}
666
667static int toshiba_touchpad_get(struct toshiba_acpi_dev *dev, u32 *state)
668{
669 u32 result;
Azael Avalos9d8658a2014-03-25 20:38:32 -0600670
671 if (!sci_open(dev))
672 return -EIO;
673
Azael Avalos893f3f62014-09-29 20:40:09 -0600674 result = sci_read(dev, SCI_TOUCHPAD, state);
Azael Avalos9d8658a2014-03-25 20:38:32 -0600675 sci_close(dev);
Azael Avalos893f3f62014-09-29 20:40:09 -0600676 if (result == TOS_FAILURE) {
Azael Avalos9d8658a2014-03-25 20:38:32 -0600677 pr_err("ACPI call to query the touchpad failed\n");
678 return -EIO;
Azael Avalos1864bbc2014-09-29 20:40:08 -0600679 } else if (result == TOS_NOT_SUPPORTED) {
Azael Avalos9d8658a2014-03-25 20:38:32 -0600680 return -ENODEV;
681 }
682
683 return 0;
684}
Pierre Ducroquet6c3f6e62010-07-29 11:56:59 +0200685
Azael Avalosdef6c4e2014-03-25 20:38:33 -0600686/* Eco Mode support */
687static int toshiba_eco_mode_available(struct toshiba_acpi_dev *dev)
688{
689 acpi_status status;
Azael Avalos98fc4ec2015-02-09 20:55:02 -0700690 u32 in[TCI_WORDS] = { HCI_GET, HCI_ECO_MODE, 0, 0, 0, 0 };
Azael Avalos258c5902014-09-29 20:40:07 -0600691 u32 out[TCI_WORDS];
Azael Avalosdef6c4e2014-03-25 20:38:33 -0600692
Azael Avalos258c5902014-09-29 20:40:07 -0600693 status = tci_raw(dev, in, out);
Azael Avalos98fc4ec2015-02-09 20:55:02 -0700694 if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) {
695 pr_err("ACPI call to get ECO led failed\n");
696 } else if (out[0] == TOS_NOT_INSTALLED) {
697 pr_info("ECO led not installed");
698 } else if (out[0] == TOS_INPUT_DATA_ERROR) {
Darren Harte0769fe2015-02-11 20:50:08 -0800699 /*
700 * If we receive 0x8300 (Input Data Error), it means that the
Azael Avalos98fc4ec2015-02-09 20:55:02 -0700701 * LED device is present, but that we just screwed the input
702 * parameters.
703 *
704 * Let's query the status of the LED to see if we really have a
705 * success response, indicating the actual presense of the LED,
706 * bail out otherwise.
707 */
708 in[3] = 1;
709 status = tci_raw(dev, in, out);
710 if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE)
711 pr_err("ACPI call to get ECO led failed\n");
712 else if (out[0] == TOS_SUCCESS)
713 return 1;
Azael Avalosdef6c4e2014-03-25 20:38:33 -0600714 }
715
Azael Avalos98fc4ec2015-02-09 20:55:02 -0700716 return 0;
Azael Avalosdef6c4e2014-03-25 20:38:33 -0600717}
718
Azael Avalosb5163992015-02-10 23:43:56 -0700719static enum led_brightness
720toshiba_eco_mode_get_status(struct led_classdev *cdev)
Azael Avalosdef6c4e2014-03-25 20:38:33 -0600721{
722 struct toshiba_acpi_dev *dev = container_of(cdev,
723 struct toshiba_acpi_dev, eco_led);
Azael Avalos258c5902014-09-29 20:40:07 -0600724 u32 in[TCI_WORDS] = { HCI_GET, HCI_ECO_MODE, 0, 1, 0, 0 };
725 u32 out[TCI_WORDS];
Azael Avalosdef6c4e2014-03-25 20:38:33 -0600726 acpi_status status;
727
Azael Avalos258c5902014-09-29 20:40:07 -0600728 status = tci_raw(dev, in, out);
Azael Avalos1864bbc2014-09-29 20:40:08 -0600729 if (ACPI_FAILURE(status) || out[0] == TOS_INPUT_DATA_ERROR) {
Azael Avalosdef6c4e2014-03-25 20:38:33 -0600730 pr_err("ACPI call to get ECO led failed\n");
731 return LED_OFF;
732 }
733
734 return out[2] ? LED_FULL : LED_OFF;
735}
736
737static void toshiba_eco_mode_set_status(struct led_classdev *cdev,
738 enum led_brightness brightness)
739{
740 struct toshiba_acpi_dev *dev = container_of(cdev,
741 struct toshiba_acpi_dev, eco_led);
Azael Avalos258c5902014-09-29 20:40:07 -0600742 u32 in[TCI_WORDS] = { HCI_SET, HCI_ECO_MODE, 0, 1, 0, 0 };
743 u32 out[TCI_WORDS];
Azael Avalosdef6c4e2014-03-25 20:38:33 -0600744 acpi_status status;
745
746 /* Switch the Eco Mode led on/off */
747 in[2] = (brightness) ? 1 : 0;
Azael Avalos258c5902014-09-29 20:40:07 -0600748 status = tci_raw(dev, in, out);
Azael Avalos1864bbc2014-09-29 20:40:08 -0600749 if (ACPI_FAILURE(status) || out[0] == TOS_INPUT_DATA_ERROR) {
Azael Avalosdef6c4e2014-03-25 20:38:33 -0600750 pr_err("ACPI call to set ECO led failed\n");
751 return;
752 }
753}
Matthew Garrettea6b31f2014-04-04 14:22:34 -0400754
Azael Avalos5a2813e2014-03-25 20:38:34 -0600755/* Accelerometer support */
756static int toshiba_accelerometer_supported(struct toshiba_acpi_dev *dev)
757{
Azael Avalos258c5902014-09-29 20:40:07 -0600758 u32 in[TCI_WORDS] = { HCI_GET, HCI_ACCELEROMETER2, 0, 0, 0, 0 };
759 u32 out[TCI_WORDS];
Azael Avalos5a2813e2014-03-25 20:38:34 -0600760 acpi_status status;
761
Darren Harte0769fe2015-02-11 20:50:08 -0800762 /*
763 * Check if the accelerometer call exists,
Azael Avalos5a2813e2014-03-25 20:38:34 -0600764 * this call also serves as initialization
765 */
Azael Avalos258c5902014-09-29 20:40:07 -0600766 status = tci_raw(dev, in, out);
Azael Avalos1864bbc2014-09-29 20:40:08 -0600767 if (ACPI_FAILURE(status) || out[0] == TOS_INPUT_DATA_ERROR) {
Azael Avalos5a2813e2014-03-25 20:38:34 -0600768 pr_err("ACPI call to query the accelerometer failed\n");
769 return -EIO;
Azael Avalos1864bbc2014-09-29 20:40:08 -0600770 } else if (out[0] == TOS_DATA_NOT_AVAILABLE ||
771 out[0] == TOS_NOT_INITIALIZED) {
Azael Avalos5a2813e2014-03-25 20:38:34 -0600772 pr_err("Accelerometer not initialized\n");
773 return -EIO;
Azael Avalos1864bbc2014-09-29 20:40:08 -0600774 } else if (out[0] == TOS_NOT_SUPPORTED) {
Azael Avalos5a2813e2014-03-25 20:38:34 -0600775 pr_info("Accelerometer not supported\n");
776 return -ENODEV;
777 }
778
779 return 0;
780}
781
782static int toshiba_accelerometer_get(struct toshiba_acpi_dev *dev,
783 u32 *xy, u32 *z)
784{
Azael Avalos258c5902014-09-29 20:40:07 -0600785 u32 in[TCI_WORDS] = { HCI_GET, HCI_ACCELEROMETER, 0, 1, 0, 0 };
786 u32 out[TCI_WORDS];
Azael Avalos5a2813e2014-03-25 20:38:34 -0600787 acpi_status status;
788
789 /* Check the Accelerometer status */
Azael Avalos258c5902014-09-29 20:40:07 -0600790 status = tci_raw(dev, in, out);
Azael Avalos1864bbc2014-09-29 20:40:08 -0600791 if (ACPI_FAILURE(status) || out[0] == TOS_INPUT_DATA_ERROR) {
Azael Avalos5a2813e2014-03-25 20:38:34 -0600792 pr_err("ACPI call to query the accelerometer failed\n");
793 return -EIO;
794 }
795
796 *xy = out[2];
797 *z = out[4];
798
799 return 0;
800}
Azael Avalosdef6c4e2014-03-25 20:38:33 -0600801
Azael Avalose26ffe52015-01-18 18:30:22 -0700802/* Sleep (Charge and Music) utilities support */
803static int toshiba_usb_sleep_charge_get(struct toshiba_acpi_dev *dev,
804 u32 *mode)
805{
806 u32 result;
807
808 if (!sci_open(dev))
809 return -EIO;
810
811 result = sci_read(dev, SCI_USB_SLEEP_CHARGE, mode);
812 sci_close(dev);
813 if (result == TOS_FAILURE) {
814 pr_err("ACPI call to set USB S&C mode failed\n");
815 return -EIO;
816 } else if (result == TOS_NOT_SUPPORTED) {
817 pr_info("USB Sleep and Charge not supported\n");
818 return -ENODEV;
819 } else if (result == TOS_INPUT_DATA_ERROR) {
820 return -EIO;
821 }
822
823 return 0;
824}
825
826static int toshiba_usb_sleep_charge_set(struct toshiba_acpi_dev *dev,
827 u32 mode)
828{
829 u32 result;
830
831 if (!sci_open(dev))
832 return -EIO;
833
834 result = sci_write(dev, SCI_USB_SLEEP_CHARGE, mode);
835 sci_close(dev);
836 if (result == TOS_FAILURE) {
837 pr_err("ACPI call to set USB S&C mode failed\n");
838 return -EIO;
839 } else if (result == TOS_NOT_SUPPORTED) {
840 pr_info("USB Sleep and Charge not supported\n");
841 return -ENODEV;
842 } else if (result == TOS_INPUT_DATA_ERROR) {
843 return -EIO;
844 }
845
846 return 0;
847}
848
Azael Avalos182bcaa2015-01-18 18:30:23 -0700849static int toshiba_sleep_functions_status_get(struct toshiba_acpi_dev *dev,
850 u32 *mode)
851{
852 u32 in[TCI_WORDS] = { SCI_GET, SCI_USB_SLEEP_CHARGE, 0, 0, 0, 0 };
853 u32 out[TCI_WORDS];
854 acpi_status status;
855
856 if (!sci_open(dev))
857 return -EIO;
858
859 in[5] = SCI_USB_CHARGE_BAT_LVL;
860 status = tci_raw(dev, in, out);
861 sci_close(dev);
862 if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) {
863 pr_err("ACPI call to get USB S&C battery level failed\n");
864 return -EIO;
865 } else if (out[0] == TOS_NOT_SUPPORTED) {
866 pr_info("USB Sleep and Charge not supported\n");
867 return -ENODEV;
868 } else if (out[0] == TOS_INPUT_DATA_ERROR) {
869 return -EIO;
870 }
871
872 *mode = out[2];
873
874 return 0;
875}
876
877static int toshiba_sleep_functions_status_set(struct toshiba_acpi_dev *dev,
878 u32 mode)
879{
880 u32 in[TCI_WORDS] = { SCI_SET, SCI_USB_SLEEP_CHARGE, 0, 0, 0, 0 };
881 u32 out[TCI_WORDS];
882 acpi_status status;
883
884 if (!sci_open(dev))
885 return -EIO;
886
887 in[2] = mode;
888 in[5] = SCI_USB_CHARGE_BAT_LVL;
889 status = tci_raw(dev, in, out);
890 sci_close(dev);
891 if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) {
892 pr_err("ACPI call to set USB S&C battery level failed\n");
893 return -EIO;
894 } else if (out[0] == TOS_NOT_SUPPORTED) {
895 pr_info("USB Sleep and Charge not supported\n");
896 return -ENODEV;
897 } else if (out[0] == TOS_INPUT_DATA_ERROR) {
898 return -EIO;
899 }
900
901 return 0;
902}
903
Azael Avalosbb3fe012015-01-18 18:30:24 -0700904static int toshiba_usb_rapid_charge_get(struct toshiba_acpi_dev *dev,
905 u32 *state)
906{
907 u32 in[TCI_WORDS] = { SCI_GET, SCI_USB_SLEEP_CHARGE, 0, 0, 0, 0 };
908 u32 out[TCI_WORDS];
909 acpi_status status;
910
911 if (!sci_open(dev))
912 return -EIO;
913
914 in[5] = SCI_USB_CHARGE_RAPID_DSP;
915 status = tci_raw(dev, in, out);
916 sci_close(dev);
917 if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) {
918 pr_err("ACPI call to get USB S&C battery level failed\n");
919 return -EIO;
920 } else if (out[0] == TOS_NOT_SUPPORTED ||
921 out[0] == TOS_INPUT_DATA_ERROR) {
922 pr_info("USB Sleep and Charge not supported\n");
923 return -ENODEV;
924 }
925
926 *state = out[2];
927
928 return 0;
929}
930
931static int toshiba_usb_rapid_charge_set(struct toshiba_acpi_dev *dev,
932 u32 state)
933{
934 u32 in[TCI_WORDS] = { SCI_SET, SCI_USB_SLEEP_CHARGE, 0, 0, 0, 0 };
935 u32 out[TCI_WORDS];
936 acpi_status status;
937
938 if (!sci_open(dev))
939 return -EIO;
940
941 in[2] = state;
942 in[5] = SCI_USB_CHARGE_RAPID_DSP;
943 status = tci_raw(dev, in, out);
944 sci_close(dev);
945 if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) {
946 pr_err("ACPI call to set USB S&C battery level failed\n");
947 return -EIO;
948 } else if (out[0] == TOS_NOT_SUPPORTED) {
949 pr_info("USB Sleep and Charge not supported\n");
950 return -ENODEV;
951 } else if (out[0] == TOS_INPUT_DATA_ERROR) {
952 return -EIO;
953 }
954
955 return 0;
956}
957
Azael Avalos172ce0a2015-01-18 18:30:25 -0700958static int toshiba_usb_sleep_music_get(struct toshiba_acpi_dev *dev, u32 *state)
959{
960 u32 result;
961
962 if (!sci_open(dev))
963 return -EIO;
964
965 result = sci_read(dev, SCI_USB_SLEEP_MUSIC, state);
966 sci_close(dev);
967 if (result == TOS_FAILURE) {
968 pr_err("ACPI call to set USB S&C mode failed\n");
969 return -EIO;
970 } else if (result == TOS_NOT_SUPPORTED) {
971 pr_info("USB Sleep and Charge not supported\n");
972 return -ENODEV;
973 } else if (result == TOS_INPUT_DATA_ERROR) {
974 return -EIO;
975 }
976
977 return 0;
978}
979
980static int toshiba_usb_sleep_music_set(struct toshiba_acpi_dev *dev, u32 state)
981{
982 u32 result;
983
984 if (!sci_open(dev))
985 return -EIO;
986
987 result = sci_write(dev, SCI_USB_SLEEP_MUSIC, state);
988 sci_close(dev);
989 if (result == TOS_FAILURE) {
990 pr_err("ACPI call to set USB S&C mode failed\n");
991 return -EIO;
992 } else if (result == TOS_NOT_SUPPORTED) {
993 pr_info("USB Sleep and Charge not supported\n");
994 return -ENODEV;
995 } else if (result == TOS_INPUT_DATA_ERROR) {
996 return -EIO;
997 }
998
999 return 0;
1000}
1001
Azael Avalosbae84192015-02-10 21:09:18 -07001002/* Keyboard function keys */
1003static int toshiba_function_keys_get(struct toshiba_acpi_dev *dev, u32 *mode)
1004{
1005 u32 result;
1006
1007 if (!sci_open(dev))
1008 return -EIO;
1009
1010 result = sci_read(dev, SCI_KBD_FUNCTION_KEYS, mode);
1011 sci_close(dev);
1012 if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) {
1013 pr_err("ACPI call to get KBD function keys failed\n");
1014 return -EIO;
1015 } else if (result == TOS_NOT_SUPPORTED) {
1016 pr_info("KBD function keys not supported\n");
1017 return -ENODEV;
1018 }
1019
1020 return 0;
1021}
1022
1023static int toshiba_function_keys_set(struct toshiba_acpi_dev *dev, u32 mode)
1024{
1025 u32 result;
1026
1027 if (!sci_open(dev))
1028 return -EIO;
1029
1030 result = sci_write(dev, SCI_KBD_FUNCTION_KEYS, mode);
1031 sci_close(dev);
1032 if (result == TOS_FAILURE || result == TOS_INPUT_DATA_ERROR) {
1033 pr_err("ACPI call to set KBD function keys failed\n");
1034 return -EIO;
1035 } else if (result == TOS_NOT_SUPPORTED) {
1036 pr_info("KBD function keys not supported\n");
1037 return -ENODEV;
1038 }
1039
1040 return 0;
1041}
1042
Azael Avalos35d53ce2015-02-10 21:09:19 -07001043/* Panel Power ON */
1044static int toshiba_panel_power_on_get(struct toshiba_acpi_dev *dev, u32 *state)
1045{
1046 u32 result;
1047
1048 if (!sci_open(dev))
1049 return -EIO;
1050
1051 result = sci_read(dev, SCI_PANEL_POWER_ON, state);
1052 sci_close(dev);
1053 if (result == TOS_FAILURE) {
1054 pr_err("ACPI call to get Panel Power ON failed\n");
1055 return -EIO;
1056 } else if (result == TOS_NOT_SUPPORTED) {
1057 pr_info("Panel Power on not supported\n");
1058 return -ENODEV;
1059 } else if (result == TOS_INPUT_DATA_ERROR) {
1060 return -EIO;
1061 }
1062
1063 return 0;
1064}
1065
1066static int toshiba_panel_power_on_set(struct toshiba_acpi_dev *dev, u32 state)
1067{
1068 u32 result;
1069
1070 if (!sci_open(dev))
1071 return -EIO;
1072
1073 result = sci_write(dev, SCI_PANEL_POWER_ON, state);
1074 sci_close(dev);
1075 if (result == TOS_FAILURE) {
1076 pr_err("ACPI call to set Panel Power ON failed\n");
1077 return -EIO;
1078 } else if (result == TOS_NOT_SUPPORTED) {
1079 pr_info("Panel Power ON not supported\n");
1080 return -ENODEV;
1081 } else if (result == TOS_INPUT_DATA_ERROR) {
1082 return -EIO;
1083 }
1084
1085 return 0;
1086}
1087
Azael Avalos17fe4b32015-02-10 21:09:20 -07001088/* USB Three */
1089static int toshiba_usb_three_get(struct toshiba_acpi_dev *dev, u32 *state)
1090{
1091 u32 result;
1092
1093 if (!sci_open(dev))
1094 return -EIO;
1095
1096 result = sci_read(dev, SCI_USB_THREE, state);
1097 sci_close(dev);
1098 if (result == TOS_FAILURE) {
1099 pr_err("ACPI call to get USB 3 failed\n");
1100 return -EIO;
1101 } else if (result == TOS_NOT_SUPPORTED) {
1102 pr_info("USB 3 not supported\n");
1103 return -ENODEV;
1104 } else if (result == TOS_INPUT_DATA_ERROR) {
1105 return -EIO;
1106 }
1107
1108 return 0;
1109}
1110
1111static int toshiba_usb_three_set(struct toshiba_acpi_dev *dev, u32 state)
1112{
1113 u32 result;
1114
1115 if (!sci_open(dev))
1116 return -EIO;
1117
1118 result = sci_write(dev, SCI_USB_THREE, state);
1119 sci_close(dev);
1120 if (result == TOS_FAILURE) {
1121 pr_err("ACPI call to set USB 3 failed\n");
1122 return -EIO;
1123 } else if (result == TOS_NOT_SUPPORTED) {
1124 pr_info("USB 3 not supported\n");
1125 return -ENODEV;
1126 } else if (result == TOS_INPUT_DATA_ERROR) {
1127 return -EIO;
1128 }
1129
1130 return 0;
1131}
1132
Azael Avalos56e6b352015-03-20 16:55:16 -06001133/* Hotkey Event type */
1134static int toshiba_hotkey_event_type_get(struct toshiba_acpi_dev *dev,
1135 u32 *type)
1136{
1137 u32 val1 = 0x03;
1138 u32 val2 = 0;
1139 u32 result;
1140
1141 result = hci_read2(dev, HCI_SYSTEM_INFO, &val1, &val2);
1142 if (result == TOS_FAILURE) {
1143 pr_err("ACPI call to get System type failed\n");
1144 return -EIO;
1145 } else if (result == TOS_NOT_SUPPORTED) {
1146 pr_info("System type not supported\n");
1147 return -ENODEV;
1148 }
1149
1150 *type = val2;
1151
1152 return 0;
1153}
1154
philipl@overt.orgc41a40c2008-08-30 11:57:39 -04001155/* Bluetooth rfkill handlers */
1156
Seth Forshee135740d2011-09-20 16:55:49 -05001157static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present)
philipl@overt.orgc41a40c2008-08-30 11:57:39 -04001158{
1159 u32 hci_result;
1160 u32 value, value2;
1161
1162 value = 0;
1163 value2 = 0;
Azael Avalos893f3f62014-09-29 20:40:09 -06001164 hci_result = hci_read2(dev, HCI_WIRELESS, &value, &value2);
Azael Avalos1864bbc2014-09-29 20:40:08 -06001165 if (hci_result == TOS_SUCCESS)
philipl@overt.orgc41a40c2008-08-30 11:57:39 -04001166 *present = (value & HCI_WIRELESS_BT_PRESENT) ? true : false;
1167
1168 return hci_result;
1169}
1170
Seth Forshee135740d2011-09-20 16:55:49 -05001171static u32 hci_get_radio_state(struct toshiba_acpi_dev *dev, bool *radio_state)
philipl@overt.orgc41a40c2008-08-30 11:57:39 -04001172{
1173 u32 hci_result;
1174 u32 value, value2;
1175
1176 value = 0;
1177 value2 = 0x0001;
Azael Avalos893f3f62014-09-29 20:40:09 -06001178 hci_result = hci_read2(dev, HCI_WIRELESS, &value, &value2);
philipl@overt.orgc41a40c2008-08-30 11:57:39 -04001179
1180 *radio_state = value & HCI_WIRELESS_KILL_SWITCH;
1181 return hci_result;
1182}
1183
Johannes Berg19d337d2009-06-02 13:01:37 +02001184static int bt_rfkill_set_block(void *data, bool blocked)
philipl@overt.orgc41a40c2008-08-30 11:57:39 -04001185{
Johannes Berg19d337d2009-06-02 13:01:37 +02001186 struct toshiba_acpi_dev *dev = data;
philipl@overt.orgc41a40c2008-08-30 11:57:39 -04001187 u32 result1, result2;
1188 u32 value;
Johannes Berg19d337d2009-06-02 13:01:37 +02001189 int err;
philipl@overt.orgc41a40c2008-08-30 11:57:39 -04001190 bool radio_state;
philipl@overt.orgc41a40c2008-08-30 11:57:39 -04001191
Johannes Berg19d337d2009-06-02 13:01:37 +02001192 value = (blocked == false);
philipl@overt.orgc41a40c2008-08-30 11:57:39 -04001193
1194 mutex_lock(&dev->mutex);
Azael Avalos1864bbc2014-09-29 20:40:08 -06001195 if (hci_get_radio_state(dev, &radio_state) != TOS_SUCCESS) {
Seth Forshee32bcd5c2011-09-20 16:55:50 -05001196 err = -EIO;
Johannes Berg19d337d2009-06-02 13:01:37 +02001197 goto out;
1198 }
1199
1200 if (!radio_state) {
1201 err = 0;
1202 goto out;
1203 }
1204
Azael Avalos893f3f62014-09-29 20:40:09 -06001205 result1 = hci_write2(dev, HCI_WIRELESS, value, HCI_WIRELESS_BT_POWER);
1206 result2 = hci_write2(dev, HCI_WIRELESS, value, HCI_WIRELESS_BT_ATTACH);
philipl@overt.orgc41a40c2008-08-30 11:57:39 -04001207
Azael Avalos1864bbc2014-09-29 20:40:08 -06001208 if (result1 != TOS_SUCCESS || result2 != TOS_SUCCESS)
Seth Forshee32bcd5c2011-09-20 16:55:50 -05001209 err = -EIO;
Johannes Berg19d337d2009-06-02 13:01:37 +02001210 else
1211 err = 0;
1212 out:
1213 mutex_unlock(&dev->mutex);
1214 return err;
philipl@overt.orgc41a40c2008-08-30 11:57:39 -04001215}
1216
Johannes Berg19d337d2009-06-02 13:01:37 +02001217static void bt_rfkill_poll(struct rfkill *rfkill, void *data)
philipl@overt.orgc41a40c2008-08-30 11:57:39 -04001218{
philipl@overt.orgc41a40c2008-08-30 11:57:39 -04001219 bool new_rfk_state;
1220 bool value;
1221 u32 hci_result;
Johannes Berg19d337d2009-06-02 13:01:37 +02001222 struct toshiba_acpi_dev *dev = data;
1223
1224 mutex_lock(&dev->mutex);
philipl@overt.orgc41a40c2008-08-30 11:57:39 -04001225
Seth Forshee135740d2011-09-20 16:55:49 -05001226 hci_result = hci_get_radio_state(dev, &value);
Azael Avalos1864bbc2014-09-29 20:40:08 -06001227 if (hci_result != TOS_SUCCESS) {
Johannes Berg19d337d2009-06-02 13:01:37 +02001228 /* Can't do anything useful */
1229 mutex_unlock(&dev->mutex);
Jiri Slaby82e77842009-08-06 15:57:51 -07001230 return;
Johannes Berg19d337d2009-06-02 13:01:37 +02001231 }
philipl@overt.orgc41a40c2008-08-30 11:57:39 -04001232
1233 new_rfk_state = value;
1234
philipl@overt.orgc41a40c2008-08-30 11:57:39 -04001235 mutex_unlock(&dev->mutex);
1236
Johannes Berg19d337d2009-06-02 13:01:37 +02001237 if (rfkill_set_hw_state(rfkill, !new_rfk_state))
1238 bt_rfkill_set_block(data, true);
philipl@overt.orgc41a40c2008-08-30 11:57:39 -04001239}
1240
Johannes Berg19d337d2009-06-02 13:01:37 +02001241static const struct rfkill_ops toshiba_rfk_ops = {
1242 .set_block = bt_rfkill_set_block,
1243 .poll = bt_rfkill_poll,
1244};
1245
Akio Idehara121b7b02012-04-06 01:46:43 +09001246static int get_tr_backlight_status(struct toshiba_acpi_dev *dev, bool *enabled)
1247{
1248 u32 hci_result;
1249 u32 status;
1250
Azael Avalos893f3f62014-09-29 20:40:09 -06001251 hci_result = hci_read1(dev, HCI_TR_BACKLIGHT, &status);
Akio Idehara121b7b02012-04-06 01:46:43 +09001252 *enabled = !status;
Azael Avalos1864bbc2014-09-29 20:40:08 -06001253 return hci_result == TOS_SUCCESS ? 0 : -EIO;
Akio Idehara121b7b02012-04-06 01:46:43 +09001254}
1255
1256static int set_tr_backlight_status(struct toshiba_acpi_dev *dev, bool enable)
1257{
1258 u32 hci_result;
1259 u32 value = !enable;
1260
Azael Avalos893f3f62014-09-29 20:40:09 -06001261 hci_result = hci_write1(dev, HCI_TR_BACKLIGHT, value);
Azael Avalos1864bbc2014-09-29 20:40:08 -06001262 return hci_result == TOS_SUCCESS ? 0 : -EIO;
Akio Idehara121b7b02012-04-06 01:46:43 +09001263}
1264
Azael Avalosb5163992015-02-10 23:43:56 -07001265static struct proc_dir_entry *toshiba_proc_dir /*= 0*/;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266
Seth Forshee62cce752012-04-19 11:23:50 -05001267static int __get_lcd_brightness(struct toshiba_acpi_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268{
1269 u32 hci_result;
1270 u32 value;
Akio Idehara121b7b02012-04-06 01:46:43 +09001271 int brightness = 0;
1272
1273 if (dev->tr_backlight_supported) {
1274 bool enabled;
1275 int ret = get_tr_backlight_status(dev, &enabled);
Azael Avalosb5163992015-02-10 23:43:56 -07001276
Akio Idehara121b7b02012-04-06 01:46:43 +09001277 if (ret)
1278 return ret;
1279 if (enabled)
1280 return 0;
1281 brightness++;
1282 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283
Azael Avalos893f3f62014-09-29 20:40:09 -06001284 hci_result = hci_read1(dev, HCI_LCD_BRIGHTNESS, &value);
Azael Avalos1864bbc2014-09-29 20:40:08 -06001285 if (hci_result == TOS_SUCCESS)
Akio Idehara121b7b02012-04-06 01:46:43 +09001286 return brightness + (value >> HCI_LCD_BRIGHTNESS_SHIFT);
Seth Forshee32bcd5c2011-09-20 16:55:50 -05001287
1288 return -EIO;
Holger Machtc9263552006-10-20 14:30:29 -07001289}
1290
Seth Forshee62cce752012-04-19 11:23:50 -05001291static int get_lcd_brightness(struct backlight_device *bd)
1292{
1293 struct toshiba_acpi_dev *dev = bl_get_data(bd);
Azael Avalosb5163992015-02-10 23:43:56 -07001294
Seth Forshee62cce752012-04-19 11:23:50 -05001295 return __get_lcd_brightness(dev);
1296}
1297
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001298static int lcd_proc_show(struct seq_file *m, void *v)
Holger Machtc9263552006-10-20 14:30:29 -07001299{
Seth Forshee135740d2011-09-20 16:55:49 -05001300 struct toshiba_acpi_dev *dev = m->private;
1301 int value;
Akio Idehara121b7b02012-04-06 01:46:43 +09001302 int levels;
Holger Machtc9263552006-10-20 14:30:29 -07001303
Seth Forshee135740d2011-09-20 16:55:49 -05001304 if (!dev->backlight_dev)
1305 return -ENODEV;
1306
Akio Idehara121b7b02012-04-06 01:46:43 +09001307 levels = dev->backlight_dev->props.max_brightness + 1;
Seth Forshee62cce752012-04-19 11:23:50 -05001308 value = get_lcd_brightness(dev->backlight_dev);
Holger Machtc9263552006-10-20 14:30:29 -07001309 if (value >= 0) {
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001310 seq_printf(m, "brightness: %d\n", value);
Akio Idehara121b7b02012-04-06 01:46:43 +09001311 seq_printf(m, "brightness_levels: %d\n", levels);
Seth Forshee32bcd5c2011-09-20 16:55:50 -05001312 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313 }
1314
Seth Forshee32bcd5c2011-09-20 16:55:50 -05001315 pr_err("Error reading LCD brightness\n");
1316 return -EIO;
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001317}
1318
1319static int lcd_proc_open(struct inode *inode, struct file *file)
1320{
Al Virod9dda782013-03-31 18:16:14 -04001321 return single_open(file, lcd_proc_show, PDE_DATA(inode));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322}
1323
Seth Forshee62cce752012-04-19 11:23:50 -05001324static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value)
Holger Machtc9263552006-10-20 14:30:29 -07001325{
Azael Avalosa39f46d2014-11-24 19:29:36 -07001326 u32 hci_result;
Holger Machtc9263552006-10-20 14:30:29 -07001327
Akio Idehara121b7b02012-04-06 01:46:43 +09001328 if (dev->tr_backlight_supported) {
1329 bool enable = !value;
1330 int ret = set_tr_backlight_status(dev, enable);
Azael Avalosb5163992015-02-10 23:43:56 -07001331
Akio Idehara121b7b02012-04-06 01:46:43 +09001332 if (ret)
1333 return ret;
1334 if (value)
1335 value--;
1336 }
1337
Azael Avalosa39f46d2014-11-24 19:29:36 -07001338 value = value << HCI_LCD_BRIGHTNESS_SHIFT;
1339 hci_result = hci_write1(dev, HCI_LCD_BRIGHTNESS, value);
1340 return hci_result == TOS_SUCCESS ? 0 : -EIO;
Holger Machtc9263552006-10-20 14:30:29 -07001341}
1342
1343static int set_lcd_status(struct backlight_device *bd)
1344{
Seth Forshee135740d2011-09-20 16:55:49 -05001345 struct toshiba_acpi_dev *dev = bl_get_data(bd);
Azael Avalosb5163992015-02-10 23:43:56 -07001346
Seth Forshee62cce752012-04-19 11:23:50 -05001347 return set_lcd_brightness(dev, bd->props.brightness);
Holger Machtc9263552006-10-20 14:30:29 -07001348}
1349
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001350static ssize_t lcd_proc_write(struct file *file, const char __user *buf,
1351 size_t count, loff_t *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352{
Al Virod9dda782013-03-31 18:16:14 -04001353 struct toshiba_acpi_dev *dev = PDE_DATA(file_inode(file));
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001354 char cmd[42];
1355 size_t len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 int value;
Matthijs van Otterdijkc8af57e2007-01-05 16:37:03 -08001357 int ret;
Akio Idehara121b7b02012-04-06 01:46:43 +09001358 int levels = dev->backlight_dev->props.max_brightness + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001360 len = min(count, sizeof(cmd) - 1);
1361 if (copy_from_user(cmd, buf, len))
1362 return -EFAULT;
1363 cmd[len] = '\0';
1364
1365 if (sscanf(cmd, " brightness : %i", &value) == 1 &&
Akio Idehara121b7b02012-04-06 01:46:43 +09001366 value >= 0 && value < levels) {
Seth Forshee62cce752012-04-19 11:23:50 -05001367 ret = set_lcd_brightness(dev, value);
Matthijs van Otterdijkc8af57e2007-01-05 16:37:03 -08001368 if (ret == 0)
1369 ret = count;
1370 } else {
Holger Machtc9263552006-10-20 14:30:29 -07001371 ret = -EINVAL;
Matthijs van Otterdijkc8af57e2007-01-05 16:37:03 -08001372 }
Holger Machtc9263552006-10-20 14:30:29 -07001373 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374}
1375
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001376static const struct file_operations lcd_proc_fops = {
1377 .owner = THIS_MODULE,
1378 .open = lcd_proc_open,
1379 .read = seq_read,
1380 .llseek = seq_lseek,
1381 .release = single_release,
1382 .write = lcd_proc_write,
1383};
1384
Seth Forshee36d03f92011-09-20 16:55:53 -05001385static int get_video_status(struct toshiba_acpi_dev *dev, u32 *status)
1386{
1387 u32 hci_result;
1388
Azael Avalos893f3f62014-09-29 20:40:09 -06001389 hci_result = hci_read1(dev, HCI_VIDEO_OUT, status);
Azael Avalos1864bbc2014-09-29 20:40:08 -06001390 return hci_result == TOS_SUCCESS ? 0 : -EIO;
Seth Forshee36d03f92011-09-20 16:55:53 -05001391}
1392
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001393static int video_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394{
Seth Forshee135740d2011-09-20 16:55:49 -05001395 struct toshiba_acpi_dev *dev = m->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 u32 value;
Seth Forshee36d03f92011-09-20 16:55:53 -05001397 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398
Seth Forshee36d03f92011-09-20 16:55:53 -05001399 ret = get_video_status(dev, &value);
1400 if (!ret) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401 int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0;
1402 int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0;
Len Brown4be44fc2005-08-05 00:44:28 -04001403 int is_tv = (value & HCI_VIDEO_OUT_TV) ? 1 : 0;
Azael Avalosb5163992015-02-10 23:43:56 -07001404
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001405 seq_printf(m, "lcd_out: %d\n", is_lcd);
1406 seq_printf(m, "crt_out: %d\n", is_crt);
1407 seq_printf(m, "tv_out: %d\n", is_tv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 }
1409
Seth Forshee36d03f92011-09-20 16:55:53 -05001410 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411}
1412
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001413static int video_proc_open(struct inode *inode, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414{
Al Virod9dda782013-03-31 18:16:14 -04001415 return single_open(file, video_proc_show, PDE_DATA(inode));
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001416}
1417
1418static ssize_t video_proc_write(struct file *file, const char __user *buf,
1419 size_t count, loff_t *pos)
1420{
Al Virod9dda782013-03-31 18:16:14 -04001421 struct toshiba_acpi_dev *dev = PDE_DATA(file_inode(file));
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001422 char *cmd, *buffer;
Seth Forshee36d03f92011-09-20 16:55:53 -05001423 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 int value;
1425 int remain = count;
1426 int lcd_out = -1;
1427 int crt_out = -1;
1428 int tv_out = -1;
Al Virob4482a42007-10-14 19:35:40 +01001429 u32 video_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001431 cmd = kmalloc(count + 1, GFP_KERNEL);
1432 if (!cmd)
1433 return -ENOMEM;
1434 if (copy_from_user(cmd, buf, count)) {
1435 kfree(cmd);
1436 return -EFAULT;
1437 }
1438 cmd[count] = '\0';
1439
1440 buffer = cmd;
1441
Darren Harte0769fe2015-02-11 20:50:08 -08001442 /*
1443 * Scan expression. Multiple expressions may be delimited with ;
1444 * NOTE: To keep scanning simple, invalid fields are ignored.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 */
1446 while (remain) {
1447 if (sscanf(buffer, " lcd_out : %i", &value) == 1)
1448 lcd_out = value & 1;
1449 else if (sscanf(buffer, " crt_out : %i", &value) == 1)
1450 crt_out = value & 1;
1451 else if (sscanf(buffer, " tv_out : %i", &value) == 1)
1452 tv_out = value & 1;
Darren Harte0769fe2015-02-11 20:50:08 -08001453 /* Advance to one character past the next ; */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 do {
1455 ++buffer;
1456 --remain;
Azael Avalosb5163992015-02-10 23:43:56 -07001457 } while (remain && *(buffer - 1) != ';');
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 }
1459
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001460 kfree(cmd);
1461
Seth Forshee36d03f92011-09-20 16:55:53 -05001462 ret = get_video_status(dev, &video_out);
1463 if (!ret) {
Harvey Harrison9e113e02008-09-22 14:37:29 -07001464 unsigned int new_video_out = video_out;
Azael Avalosb5163992015-02-10 23:43:56 -07001465
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 if (lcd_out != -1)
1467 _set_bit(&new_video_out, HCI_VIDEO_OUT_LCD, lcd_out);
1468 if (crt_out != -1)
1469 _set_bit(&new_video_out, HCI_VIDEO_OUT_CRT, crt_out);
1470 if (tv_out != -1)
1471 _set_bit(&new_video_out, HCI_VIDEO_OUT_TV, tv_out);
Darren Harte0769fe2015-02-11 20:50:08 -08001472 /*
1473 * To avoid unnecessary video disruption, only write the new
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 * video setting if something changed. */
1475 if (new_video_out != video_out)
Seth Forshee32bcd5c2011-09-20 16:55:50 -05001476 ret = write_acpi_int(METHOD_VIDEO_OUT, new_video_out);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477 }
1478
Seth Forshee32bcd5c2011-09-20 16:55:50 -05001479 return ret ? ret : count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480}
1481
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001482static const struct file_operations video_proc_fops = {
1483 .owner = THIS_MODULE,
1484 .open = video_proc_open,
1485 .read = seq_read,
1486 .llseek = seq_lseek,
1487 .release = single_release,
1488 .write = video_proc_write,
1489};
1490
Seth Forshee36d03f92011-09-20 16:55:53 -05001491static int get_fan_status(struct toshiba_acpi_dev *dev, u32 *status)
1492{
1493 u32 hci_result;
1494
Azael Avalos893f3f62014-09-29 20:40:09 -06001495 hci_result = hci_read1(dev, HCI_FAN, status);
Azael Avalos1864bbc2014-09-29 20:40:08 -06001496 return hci_result == TOS_SUCCESS ? 0 : -EIO;
Seth Forshee36d03f92011-09-20 16:55:53 -05001497}
1498
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001499static int fan_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500{
Seth Forshee135740d2011-09-20 16:55:49 -05001501 struct toshiba_acpi_dev *dev = m->private;
Seth Forshee36d03f92011-09-20 16:55:53 -05001502 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 u32 value;
1504
Seth Forshee36d03f92011-09-20 16:55:53 -05001505 ret = get_fan_status(dev, &value);
1506 if (!ret) {
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001507 seq_printf(m, "running: %d\n", (value > 0));
Seth Forshee135740d2011-09-20 16:55:49 -05001508 seq_printf(m, "force_on: %d\n", dev->force_fan);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509 }
1510
Seth Forshee36d03f92011-09-20 16:55:53 -05001511 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512}
1513
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001514static int fan_proc_open(struct inode *inode, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515{
Al Virod9dda782013-03-31 18:16:14 -04001516 return single_open(file, fan_proc_show, PDE_DATA(inode));
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001517}
1518
1519static ssize_t fan_proc_write(struct file *file, const char __user *buf,
1520 size_t count, loff_t *pos)
1521{
Al Virod9dda782013-03-31 18:16:14 -04001522 struct toshiba_acpi_dev *dev = PDE_DATA(file_inode(file));
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001523 char cmd[42];
1524 size_t len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525 int value;
1526 u32 hci_result;
1527
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001528 len = min(count, sizeof(cmd) - 1);
1529 if (copy_from_user(cmd, buf, len))
1530 return -EFAULT;
1531 cmd[len] = '\0';
1532
1533 if (sscanf(cmd, " force_on : %i", &value) == 1 &&
Len Brown4be44fc2005-08-05 00:44:28 -04001534 value >= 0 && value <= 1) {
Azael Avalos893f3f62014-09-29 20:40:09 -06001535 hci_result = hci_write1(dev, HCI_FAN, value);
Azael Avalosb5163992015-02-10 23:43:56 -07001536 if (hci_result == TOS_SUCCESS)
Seth Forshee135740d2011-09-20 16:55:49 -05001537 dev->force_fan = value;
Azael Avalosb5163992015-02-10 23:43:56 -07001538 else
1539 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 } else {
1541 return -EINVAL;
1542 }
1543
1544 return count;
1545}
1546
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001547static const struct file_operations fan_proc_fops = {
1548 .owner = THIS_MODULE,
1549 .open = fan_proc_open,
1550 .read = seq_read,
1551 .llseek = seq_lseek,
1552 .release = single_release,
1553 .write = fan_proc_write,
1554};
1555
1556static int keys_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557{
Seth Forshee135740d2011-09-20 16:55:49 -05001558 struct toshiba_acpi_dev *dev = m->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 u32 hci_result;
1560 u32 value;
1561
Seth Forshee11948b92011-11-16 17:37:45 -06001562 if (!dev->key_event_valid && dev->system_event_supported) {
Azael Avalos893f3f62014-09-29 20:40:09 -06001563 hci_result = hci_read1(dev, HCI_SYSTEM_EVENT, &value);
Azael Avalos1864bbc2014-09-29 20:40:08 -06001564 if (hci_result == TOS_SUCCESS) {
Seth Forshee135740d2011-09-20 16:55:49 -05001565 dev->key_event_valid = 1;
1566 dev->last_key_event = value;
Azael Avalos1864bbc2014-09-29 20:40:08 -06001567 } else if (hci_result == TOS_FIFO_EMPTY) {
Darren Harte0769fe2015-02-11 20:50:08 -08001568 /* Better luck next time */
Azael Avalos1864bbc2014-09-29 20:40:08 -06001569 } else if (hci_result == TOS_NOT_SUPPORTED) {
Darren Harte0769fe2015-02-11 20:50:08 -08001570 /*
1571 * This is a workaround for an unresolved issue on
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572 * some machines where system events sporadically
Darren Harte0769fe2015-02-11 20:50:08 -08001573 * become disabled.
1574 */
Azael Avalos893f3f62014-09-29 20:40:09 -06001575 hci_result = hci_write1(dev, HCI_SYSTEM_EVENT, 1);
Joe Perches7e334602011-03-29 15:21:52 -07001576 pr_notice("Re-enabled hotkeys\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577 } else {
Joe Perches7e334602011-03-29 15:21:52 -07001578 pr_err("Error reading hotkey status\n");
Seth Forshee32bcd5c2011-09-20 16:55:50 -05001579 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 }
1581 }
1582
Seth Forshee135740d2011-09-20 16:55:49 -05001583 seq_printf(m, "hotkey_ready: %d\n", dev->key_event_valid);
1584 seq_printf(m, "hotkey: 0x%04x\n", dev->last_key_event);
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001585 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586}
1587
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001588static int keys_proc_open(struct inode *inode, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589{
Al Virod9dda782013-03-31 18:16:14 -04001590 return single_open(file, keys_proc_show, PDE_DATA(inode));
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001591}
1592
1593static ssize_t keys_proc_write(struct file *file, const char __user *buf,
1594 size_t count, loff_t *pos)
1595{
Al Virod9dda782013-03-31 18:16:14 -04001596 struct toshiba_acpi_dev *dev = PDE_DATA(file_inode(file));
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001597 char cmd[42];
1598 size_t len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 int value;
1600
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001601 len = min(count, sizeof(cmd) - 1);
1602 if (copy_from_user(cmd, buf, len))
1603 return -EFAULT;
1604 cmd[len] = '\0';
1605
Azael Avalosb5163992015-02-10 23:43:56 -07001606 if (sscanf(cmd, " hotkey_ready : %i", &value) == 1 && value == 0)
Seth Forshee135740d2011-09-20 16:55:49 -05001607 dev->key_event_valid = 0;
Azael Avalosb5163992015-02-10 23:43:56 -07001608 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610
1611 return count;
1612}
1613
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001614static const struct file_operations keys_proc_fops = {
1615 .owner = THIS_MODULE,
1616 .open = keys_proc_open,
1617 .read = seq_read,
1618 .llseek = seq_lseek,
1619 .release = single_release,
1620 .write = keys_proc_write,
1621};
1622
1623static int version_proc_show(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624{
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001625 seq_printf(m, "driver: %s\n", TOSHIBA_ACPI_VERSION);
1626 seq_printf(m, "proc_interface: %d\n", PROC_INTERFACE_VERSION);
1627 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628}
1629
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001630static int version_proc_open(struct inode *inode, struct file *file)
1631{
Al Virod9dda782013-03-31 18:16:14 -04001632 return single_open(file, version_proc_show, PDE_DATA(inode));
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001633}
1634
1635static const struct file_operations version_proc_fops = {
1636 .owner = THIS_MODULE,
1637 .open = version_proc_open,
1638 .read = seq_read,
1639 .llseek = seq_lseek,
1640 .release = single_release,
1641};
1642
Darren Harte0769fe2015-02-11 20:50:08 -08001643/*
1644 * Proc and module init
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645 */
1646
1647#define PROC_TOSHIBA "toshiba"
1648
Greg Kroah-Hartmanb859f152012-12-21 13:18:33 -08001649static void create_toshiba_proc_entries(struct toshiba_acpi_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650{
Seth Forshee36d03f92011-09-20 16:55:53 -05001651 if (dev->backlight_dev)
1652 proc_create_data("lcd", S_IRUGO | S_IWUSR, toshiba_proc_dir,
1653 &lcd_proc_fops, dev);
1654 if (dev->video_supported)
1655 proc_create_data("video", S_IRUGO | S_IWUSR, toshiba_proc_dir,
1656 &video_proc_fops, dev);
1657 if (dev->fan_supported)
1658 proc_create_data("fan", S_IRUGO | S_IWUSR, toshiba_proc_dir,
1659 &fan_proc_fops, dev);
1660 if (dev->hotkey_dev)
1661 proc_create_data("keys", S_IRUGO | S_IWUSR, toshiba_proc_dir,
1662 &keys_proc_fops, dev);
Seth Forshee135740d2011-09-20 16:55:49 -05001663 proc_create_data("version", S_IRUGO, toshiba_proc_dir,
1664 &version_proc_fops, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665}
1666
Seth Forshee36d03f92011-09-20 16:55:53 -05001667static void remove_toshiba_proc_entries(struct toshiba_acpi_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668{
Seth Forshee36d03f92011-09-20 16:55:53 -05001669 if (dev->backlight_dev)
1670 remove_proc_entry("lcd", toshiba_proc_dir);
1671 if (dev->video_supported)
1672 remove_proc_entry("video", toshiba_proc_dir);
1673 if (dev->fan_supported)
1674 remove_proc_entry("fan", toshiba_proc_dir);
1675 if (dev->hotkey_dev)
1676 remove_proc_entry("keys", toshiba_proc_dir);
Alexey Dobriyan936c8bc2009-12-21 16:20:02 -08001677 remove_proc_entry("version", toshiba_proc_dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678}
1679
Lionel Debrouxacc24722010-11-16 14:14:02 +01001680static const struct backlight_ops toshiba_backlight_data = {
Akio Idehara121b7b02012-04-06 01:46:43 +09001681 .options = BL_CORE_SUSPENDRESUME,
Seth Forshee62cce752012-04-19 11:23:50 -05001682 .get_brightness = get_lcd_brightness,
1683 .update_status = set_lcd_status,
Holger Machtc9263552006-10-20 14:30:29 -07001684};
Matthew Garrettea6b31f2014-04-04 14:22:34 -04001685
Azael Avalos360f0f32014-03-25 20:38:31 -06001686/*
1687 * Sysfs files
1688 */
Azael Avalos9d309842015-02-10 23:43:59 -07001689static ssize_t version_show(struct device *dev,
1690 struct device_attribute *attr, char *buf)
Azael Avalosc6c68ff2015-02-10 21:09:16 -07001691{
1692 return sprintf(buf, "%s\n", TOSHIBA_ACPI_VERSION);
1693}
Azael Avalos0c3c0f12015-02-10 23:44:00 -07001694static DEVICE_ATTR_RO(version);
Azael Avalosc6c68ff2015-02-10 21:09:16 -07001695
Azael Avalos9d309842015-02-10 23:43:59 -07001696static ssize_t fan_store(struct device *dev,
1697 struct device_attribute *attr,
1698 const char *buf, size_t count)
Azael Avalos94477d42015-02-10 21:09:17 -07001699{
1700 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
1701 u32 result;
1702 int state;
1703 int ret;
1704
1705 ret = kstrtoint(buf, 0, &state);
1706 if (ret)
1707 return ret;
1708
1709 if (state != 0 && state != 1)
1710 return -EINVAL;
1711
1712 result = hci_write1(toshiba, HCI_FAN, state);
1713 if (result == TOS_FAILURE)
1714 return -EIO;
1715 else if (result == TOS_NOT_SUPPORTED)
1716 return -ENODEV;
1717
1718 return count;
1719}
1720
Azael Avalos9d309842015-02-10 23:43:59 -07001721static ssize_t fan_show(struct device *dev,
1722 struct device_attribute *attr, char *buf)
Azael Avalos94477d42015-02-10 21:09:17 -07001723{
1724 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
1725 u32 value;
1726 int ret;
1727
1728 ret = get_fan_status(toshiba, &value);
1729 if (ret)
1730 return ret;
1731
1732 return sprintf(buf, "%d\n", value);
1733}
Azael Avalos0c3c0f12015-02-10 23:44:00 -07001734static DEVICE_ATTR_RW(fan);
Azael Avalos94477d42015-02-10 21:09:17 -07001735
Azael Avalos9d309842015-02-10 23:43:59 -07001736static ssize_t kbd_backlight_mode_store(struct device *dev,
1737 struct device_attribute *attr,
1738 const char *buf, size_t count)
Azael Avalos360f0f32014-03-25 20:38:31 -06001739{
1740 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
Dan Carpenteraeaac092014-09-03 14:44:37 +03001741 int mode;
1742 int time;
1743 int ret;
Azael Avalos360f0f32014-03-25 20:38:31 -06001744
Dan Carpenteraeaac092014-09-03 14:44:37 +03001745
1746 ret = kstrtoint(buf, 0, &mode);
1747 if (ret)
1748 return ret;
Azael Avalos93f8c162014-09-12 18:50:36 -06001749
1750 /* Check for supported modes depending on keyboard backlight type */
1751 if (toshiba->kbd_type == 1) {
1752 /* Type 1 supports SCI_KBD_MODE_FNZ and SCI_KBD_MODE_AUTO */
1753 if (mode != SCI_KBD_MODE_FNZ && mode != SCI_KBD_MODE_AUTO)
1754 return -EINVAL;
1755 } else if (toshiba->kbd_type == 2) {
1756 /* Type 2 doesn't support SCI_KBD_MODE_FNZ */
1757 if (mode != SCI_KBD_MODE_AUTO && mode != SCI_KBD_MODE_ON &&
1758 mode != SCI_KBD_MODE_OFF)
1759 return -EINVAL;
1760 }
Azael Avalos360f0f32014-03-25 20:38:31 -06001761
Darren Harte0769fe2015-02-11 20:50:08 -08001762 /*
1763 * Set the Keyboard Backlight Mode where:
Azael Avalos360f0f32014-03-25 20:38:31 -06001764 * Auto - KBD backlight turns off automatically in given time
1765 * FN-Z - KBD backlight "toggles" when hotkey pressed
Azael Avalos93f8c162014-09-12 18:50:36 -06001766 * ON - KBD backlight is always on
1767 * OFF - KBD backlight is always off
Azael Avalos360f0f32014-03-25 20:38:31 -06001768 */
Azael Avalos93f8c162014-09-12 18:50:36 -06001769
1770 /* Only make a change if the actual mode has changed */
Dan Carpenteraeaac092014-09-03 14:44:37 +03001771 if (toshiba->kbd_mode != mode) {
Azael Avalos93f8c162014-09-12 18:50:36 -06001772 /* Shift the time to "base time" (0x3c0000 == 60 seconds) */
Azael Avalos360f0f32014-03-25 20:38:31 -06001773 time = toshiba->kbd_time << HCI_MISC_SHIFT;
Azael Avalos93f8c162014-09-12 18:50:36 -06001774
1775 /* OR the "base time" to the actual method format */
1776 if (toshiba->kbd_type == 1) {
1777 /* Type 1 requires the current mode */
1778 time |= toshiba->kbd_mode;
1779 } else if (toshiba->kbd_type == 2) {
1780 /* Type 2 requires the desired mode */
1781 time |= mode;
1782 }
1783
Dan Carpenteraeaac092014-09-03 14:44:37 +03001784 ret = toshiba_kbd_illum_status_set(toshiba, time);
1785 if (ret)
1786 return ret;
Azael Avalos93f8c162014-09-12 18:50:36 -06001787
Azael Avalos360f0f32014-03-25 20:38:31 -06001788 toshiba->kbd_mode = mode;
1789 }
1790
1791 return count;
1792}
1793
Azael Avalos9d309842015-02-10 23:43:59 -07001794static ssize_t kbd_backlight_mode_show(struct device *dev,
1795 struct device_attribute *attr,
1796 char *buf)
Azael Avalos360f0f32014-03-25 20:38:31 -06001797{
1798 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
1799 u32 time;
1800
1801 if (toshiba_kbd_illum_status_get(toshiba, &time) < 0)
1802 return -EIO;
1803
Azael Avalos93f8c162014-09-12 18:50:36 -06001804 return sprintf(buf, "%i\n", time & SCI_KBD_MODE_MASK);
1805}
Azael Avalos0c3c0f12015-02-10 23:44:00 -07001806static DEVICE_ATTR_RW(kbd_backlight_mode);
Azael Avalos93f8c162014-09-12 18:50:36 -06001807
Azael Avalos9d309842015-02-10 23:43:59 -07001808static ssize_t kbd_type_show(struct device *dev,
1809 struct device_attribute *attr, char *buf)
Azael Avalos93f8c162014-09-12 18:50:36 -06001810{
1811 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
1812
1813 return sprintf(buf, "%d\n", toshiba->kbd_type);
1814}
Azael Avalos0c3c0f12015-02-10 23:44:00 -07001815static DEVICE_ATTR_RO(kbd_type);
Azael Avalos93f8c162014-09-12 18:50:36 -06001816
Azael Avalos9d309842015-02-10 23:43:59 -07001817static ssize_t available_kbd_modes_show(struct device *dev,
1818 struct device_attribute *attr,
1819 char *buf)
Azael Avalos93f8c162014-09-12 18:50:36 -06001820{
1821 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
1822
1823 if (toshiba->kbd_type == 1)
1824 return sprintf(buf, "%x %x\n",
1825 SCI_KBD_MODE_FNZ, SCI_KBD_MODE_AUTO);
1826
1827 return sprintf(buf, "%x %x %x\n",
1828 SCI_KBD_MODE_AUTO, SCI_KBD_MODE_ON, SCI_KBD_MODE_OFF);
Azael Avalos360f0f32014-03-25 20:38:31 -06001829}
Azael Avalos0c3c0f12015-02-10 23:44:00 -07001830static DEVICE_ATTR_RO(available_kbd_modes);
Azael Avalos360f0f32014-03-25 20:38:31 -06001831
Azael Avalos9d309842015-02-10 23:43:59 -07001832static ssize_t kbd_backlight_timeout_store(struct device *dev,
1833 struct device_attribute *attr,
1834 const char *buf, size_t count)
Azael Avalos360f0f32014-03-25 20:38:31 -06001835{
1836 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
Azael Avaloseabde0f2014-10-04 12:02:21 -06001837 int time;
1838 int ret;
Azael Avalos360f0f32014-03-25 20:38:31 -06001839
Azael Avaloseabde0f2014-10-04 12:02:21 -06001840 ret = kstrtoint(buf, 0, &time);
1841 if (ret)
1842 return ret;
Azael Avalos360f0f32014-03-25 20:38:31 -06001843
Azael Avaloseabde0f2014-10-04 12:02:21 -06001844 /* Check for supported values depending on kbd_type */
1845 if (toshiba->kbd_type == 1) {
1846 if (time < 0 || time > 60)
1847 return -EINVAL;
1848 } else if (toshiba->kbd_type == 2) {
1849 if (time < 1 || time > 60)
1850 return -EINVAL;
1851 }
1852
1853 /* Set the Keyboard Backlight Timeout */
1854
1855 /* Only make a change if the actual timeout has changed */
1856 if (toshiba->kbd_time != time) {
1857 /* Shift the time to "base time" (0x3c0000 == 60 seconds) */
Azael Avalos360f0f32014-03-25 20:38:31 -06001858 time = time << HCI_MISC_SHIFT;
Azael Avaloseabde0f2014-10-04 12:02:21 -06001859 /* OR the "base time" to the actual method format */
1860 if (toshiba->kbd_type == 1)
1861 time |= SCI_KBD_MODE_FNZ;
1862 else if (toshiba->kbd_type == 2)
1863 time |= SCI_KBD_MODE_AUTO;
1864
1865 ret = toshiba_kbd_illum_status_set(toshiba, time);
1866 if (ret)
1867 return ret;
1868
Azael Avalos360f0f32014-03-25 20:38:31 -06001869 toshiba->kbd_time = time >> HCI_MISC_SHIFT;
1870 }
1871
1872 return count;
1873}
1874
Azael Avalos9d309842015-02-10 23:43:59 -07001875static ssize_t kbd_backlight_timeout_show(struct device *dev,
1876 struct device_attribute *attr,
1877 char *buf)
Azael Avalos360f0f32014-03-25 20:38:31 -06001878{
1879 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
1880 u32 time;
1881
1882 if (toshiba_kbd_illum_status_get(toshiba, &time) < 0)
1883 return -EIO;
1884
1885 return sprintf(buf, "%i\n", time >> HCI_MISC_SHIFT);
1886}
Azael Avalos0c3c0f12015-02-10 23:44:00 -07001887static DEVICE_ATTR_RW(kbd_backlight_timeout);
Matthew Garrettea6b31f2014-04-04 14:22:34 -04001888
Azael Avalos9d309842015-02-10 23:43:59 -07001889static ssize_t touchpad_store(struct device *dev,
1890 struct device_attribute *attr,
1891 const char *buf, size_t count)
Azael Avalos9d8658a2014-03-25 20:38:32 -06001892{
1893 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
1894 int state;
Azael Avalosc8a41662014-09-10 21:01:57 -06001895 int ret;
Azael Avalos9d8658a2014-03-25 20:38:32 -06001896
1897 /* Set the TouchPad on/off, 0 - Disable | 1 - Enable */
Azael Avalosc8a41662014-09-10 21:01:57 -06001898 ret = kstrtoint(buf, 0, &state);
1899 if (ret)
1900 return ret;
1901 if (state != 0 && state != 1)
1902 return -EINVAL;
1903
1904 ret = toshiba_touchpad_set(toshiba, state);
1905 if (ret)
1906 return ret;
Azael Avalos9d8658a2014-03-25 20:38:32 -06001907
1908 return count;
1909}
1910
Azael Avalos9d309842015-02-10 23:43:59 -07001911static ssize_t touchpad_show(struct device *dev,
1912 struct device_attribute *attr, char *buf)
Azael Avalos9d8658a2014-03-25 20:38:32 -06001913{
1914 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
1915 u32 state;
1916 int ret;
1917
1918 ret = toshiba_touchpad_get(toshiba, &state);
1919 if (ret < 0)
1920 return ret;
1921
1922 return sprintf(buf, "%i\n", state);
1923}
Azael Avalos0c3c0f12015-02-10 23:44:00 -07001924static DEVICE_ATTR_RW(touchpad);
Matthew Garrettea6b31f2014-04-04 14:22:34 -04001925
Azael Avalos9d309842015-02-10 23:43:59 -07001926static ssize_t position_show(struct device *dev,
1927 struct device_attribute *attr, char *buf)
Azael Avalos5a2813e2014-03-25 20:38:34 -06001928{
1929 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
1930 u32 xyval, zval, tmp;
1931 u16 x, y, z;
1932 int ret;
1933
1934 xyval = zval = 0;
1935 ret = toshiba_accelerometer_get(toshiba, &xyval, &zval);
1936 if (ret < 0)
1937 return ret;
1938
1939 x = xyval & HCI_ACCEL_MASK;
1940 tmp = xyval >> HCI_MISC_SHIFT;
1941 y = tmp & HCI_ACCEL_MASK;
1942 z = zval & HCI_ACCEL_MASK;
1943
1944 return sprintf(buf, "%d %d %d\n", x, y, z);
1945}
Azael Avalos0c3c0f12015-02-10 23:44:00 -07001946static DEVICE_ATTR_RO(position);
Azael Avalos360f0f32014-03-25 20:38:31 -06001947
Azael Avalos9d309842015-02-10 23:43:59 -07001948static ssize_t usb_sleep_charge_show(struct device *dev,
1949 struct device_attribute *attr, char *buf)
Azael Avalose26ffe52015-01-18 18:30:22 -07001950{
1951 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
1952 u32 mode;
1953 int ret;
1954
1955 ret = toshiba_usb_sleep_charge_get(toshiba, &mode);
1956 if (ret < 0)
1957 return ret;
1958
1959 return sprintf(buf, "%x\n", mode & SCI_USB_CHARGE_MODE_MASK);
1960}
1961
Azael Avalos9d309842015-02-10 23:43:59 -07001962static ssize_t usb_sleep_charge_store(struct device *dev,
1963 struct device_attribute *attr,
1964 const char *buf, size_t count)
Azael Avalose26ffe52015-01-18 18:30:22 -07001965{
1966 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
1967 u32 mode;
1968 int state;
1969 int ret;
1970
1971 ret = kstrtoint(buf, 0, &state);
1972 if (ret)
1973 return ret;
Darren Harte0769fe2015-02-11 20:50:08 -08001974 /*
1975 * Check for supported values, where:
Azael Avalose26ffe52015-01-18 18:30:22 -07001976 * 0 - Disabled
1977 * 1 - Alternate (Non USB conformant devices that require more power)
1978 * 2 - Auto (USB conformant devices)
1979 */
1980 if (state != 0 && state != 1 && state != 2)
1981 return -EINVAL;
1982
1983 /* Set the USB charging mode to internal value */
1984 if (state == 0)
1985 mode = SCI_USB_CHARGE_DISABLED;
1986 else if (state == 1)
1987 mode = SCI_USB_CHARGE_ALTERNATE;
1988 else if (state == 2)
1989 mode = SCI_USB_CHARGE_AUTO;
1990
1991 ret = toshiba_usb_sleep_charge_set(toshiba, mode);
1992 if (ret)
1993 return ret;
1994
1995 return count;
1996}
Azael Avalos0c3c0f12015-02-10 23:44:00 -07001997static DEVICE_ATTR_RW(usb_sleep_charge);
Azael Avalose26ffe52015-01-18 18:30:22 -07001998
Azael Avalos182bcaa2015-01-18 18:30:23 -07001999static ssize_t sleep_functions_on_battery_show(struct device *dev,
2000 struct device_attribute *attr,
2001 char *buf)
2002{
2003 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
2004 u32 state;
2005 int bat_lvl;
2006 int status;
2007 int ret;
2008 int tmp;
2009
2010 ret = toshiba_sleep_functions_status_get(toshiba, &state);
2011 if (ret < 0)
2012 return ret;
2013
2014 /* Determine the status: 0x4 - Enabled | 0x1 - Disabled */
2015 tmp = state & SCI_USB_CHARGE_BAT_MASK;
2016 status = (tmp == 0x4) ? 1 : 0;
2017 /* Determine the battery level set */
2018 bat_lvl = state >> HCI_MISC_SHIFT;
2019
2020 return sprintf(buf, "%d %d\n", status, bat_lvl);
2021}
2022
2023static ssize_t sleep_functions_on_battery_store(struct device *dev,
2024 struct device_attribute *attr,
2025 const char *buf, size_t count)
2026{
2027 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
2028 u32 status;
2029 int value;
2030 int ret;
2031 int tmp;
2032
2033 ret = kstrtoint(buf, 0, &value);
2034 if (ret)
2035 return ret;
2036
Darren Harte0769fe2015-02-11 20:50:08 -08002037 /*
2038 * Set the status of the function:
Azael Avalos182bcaa2015-01-18 18:30:23 -07002039 * 0 - Disabled
2040 * 1-100 - Enabled
2041 */
2042 if (value < 0 || value > 100)
2043 return -EINVAL;
2044
2045 if (value == 0) {
2046 tmp = toshiba->usbsc_bat_level << HCI_MISC_SHIFT;
2047 status = tmp | SCI_USB_CHARGE_BAT_LVL_OFF;
2048 } else {
2049 tmp = value << HCI_MISC_SHIFT;
2050 status = tmp | SCI_USB_CHARGE_BAT_LVL_ON;
2051 }
2052 ret = toshiba_sleep_functions_status_set(toshiba, status);
2053 if (ret < 0)
2054 return ret;
2055
2056 toshiba->usbsc_bat_level = status >> HCI_MISC_SHIFT;
2057
2058 return count;
2059}
Azael Avalos0c3c0f12015-02-10 23:44:00 -07002060static DEVICE_ATTR_RW(sleep_functions_on_battery);
Azael Avalos182bcaa2015-01-18 18:30:23 -07002061
Azael Avalos9d309842015-02-10 23:43:59 -07002062static ssize_t usb_rapid_charge_show(struct device *dev,
2063 struct device_attribute *attr, char *buf)
Azael Avalosbb3fe012015-01-18 18:30:24 -07002064{
2065 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
2066 u32 state;
2067 int ret;
2068
2069 ret = toshiba_usb_rapid_charge_get(toshiba, &state);
2070 if (ret < 0)
2071 return ret;
2072
2073 return sprintf(buf, "%d\n", state);
2074}
2075
Azael Avalos9d309842015-02-10 23:43:59 -07002076static ssize_t usb_rapid_charge_store(struct device *dev,
2077 struct device_attribute *attr,
2078 const char *buf, size_t count)
Azael Avalosbb3fe012015-01-18 18:30:24 -07002079{
2080 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
2081 int state;
2082 int ret;
2083
2084 ret = kstrtoint(buf, 0, &state);
2085 if (ret)
2086 return ret;
2087 if (state != 0 && state != 1)
2088 return -EINVAL;
2089
2090 ret = toshiba_usb_rapid_charge_set(toshiba, state);
2091 if (ret)
2092 return ret;
2093
2094 return count;
2095}
Azael Avalos0c3c0f12015-02-10 23:44:00 -07002096static DEVICE_ATTR_RW(usb_rapid_charge);
Azael Avalosbb3fe012015-01-18 18:30:24 -07002097
Azael Avalos9d309842015-02-10 23:43:59 -07002098static ssize_t usb_sleep_music_show(struct device *dev,
2099 struct device_attribute *attr, char *buf)
Azael Avalos172ce0a2015-01-18 18:30:25 -07002100{
2101 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
2102 u32 state;
2103 int ret;
2104
2105 ret = toshiba_usb_sleep_music_get(toshiba, &state);
2106 if (ret < 0)
2107 return ret;
2108
2109 return sprintf(buf, "%d\n", state);
2110}
2111
Azael Avalos9d309842015-02-10 23:43:59 -07002112static ssize_t usb_sleep_music_store(struct device *dev,
2113 struct device_attribute *attr,
2114 const char *buf, size_t count)
Azael Avalos172ce0a2015-01-18 18:30:25 -07002115{
2116 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
2117 int state;
2118 int ret;
2119
2120 ret = kstrtoint(buf, 0, &state);
2121 if (ret)
2122 return ret;
2123 if (state != 0 && state != 1)
2124 return -EINVAL;
2125
2126 ret = toshiba_usb_sleep_music_set(toshiba, state);
2127 if (ret)
2128 return ret;
2129
2130 return count;
2131}
Azael Avalos0c3c0f12015-02-10 23:44:00 -07002132static DEVICE_ATTR_RW(usb_sleep_music);
Azael Avalos172ce0a2015-01-18 18:30:25 -07002133
Azael Avalos9d309842015-02-10 23:43:59 -07002134static ssize_t kbd_function_keys_show(struct device *dev,
2135 struct device_attribute *attr, char *buf)
Azael Avalosbae84192015-02-10 21:09:18 -07002136{
2137 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
2138 int mode;
2139 int ret;
2140
2141 ret = toshiba_function_keys_get(toshiba, &mode);
2142 if (ret < 0)
2143 return ret;
2144
2145 return sprintf(buf, "%d\n", mode);
2146}
2147
Azael Avalos9d309842015-02-10 23:43:59 -07002148static ssize_t kbd_function_keys_store(struct device *dev,
2149 struct device_attribute *attr,
2150 const char *buf, size_t count)
Azael Avalosbae84192015-02-10 21:09:18 -07002151{
2152 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
2153 int mode;
2154 int ret;
2155
2156 ret = kstrtoint(buf, 0, &mode);
2157 if (ret)
2158 return ret;
Darren Harte0769fe2015-02-11 20:50:08 -08002159 /*
2160 * Check for the function keys mode where:
Azael Avalosbae84192015-02-10 21:09:18 -07002161 * 0 - Normal operation (F{1-12} as usual and hotkeys via FN-F{1-12})
2162 * 1 - Special functions (Opposite of the above setting)
2163 */
2164 if (mode != 0 && mode != 1)
2165 return -EINVAL;
2166
2167 ret = toshiba_function_keys_set(toshiba, mode);
2168 if (ret)
2169 return ret;
2170
2171 pr_info("Reboot for changes to KBD Function Keys to take effect");
2172
2173 return count;
2174}
Azael Avalos0c3c0f12015-02-10 23:44:00 -07002175static DEVICE_ATTR_RW(kbd_function_keys);
Azael Avalosbae84192015-02-10 21:09:18 -07002176
Azael Avalos9d309842015-02-10 23:43:59 -07002177static ssize_t panel_power_on_show(struct device *dev,
2178 struct device_attribute *attr, char *buf)
Azael Avalos35d53ce2015-02-10 21:09:19 -07002179{
2180 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
2181 u32 state;
2182 int ret;
2183
2184 ret = toshiba_panel_power_on_get(toshiba, &state);
2185 if (ret < 0)
2186 return ret;
2187
2188 return sprintf(buf, "%d\n", state);
2189}
2190
Azael Avalos9d309842015-02-10 23:43:59 -07002191static ssize_t panel_power_on_store(struct device *dev,
2192 struct device_attribute *attr,
2193 const char *buf, size_t count)
Azael Avalos35d53ce2015-02-10 21:09:19 -07002194{
2195 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
2196 int state;
2197 int ret;
2198
2199 ret = kstrtoint(buf, 0, &state);
2200 if (ret)
2201 return ret;
2202 if (state != 0 && state != 1)
2203 return -EINVAL;
2204
2205 ret = toshiba_panel_power_on_set(toshiba, state);
2206 if (ret)
2207 return ret;
2208
2209 pr_info("Reboot for changes to Panel Power ON to take effect");
2210
2211 return count;
2212}
Azael Avalos0c3c0f12015-02-10 23:44:00 -07002213static DEVICE_ATTR_RW(panel_power_on);
Azael Avalos35d53ce2015-02-10 21:09:19 -07002214
Azael Avalos9d309842015-02-10 23:43:59 -07002215static ssize_t usb_three_show(struct device *dev,
2216 struct device_attribute *attr, char *buf)
Azael Avalos17fe4b32015-02-10 21:09:20 -07002217{
2218 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
2219 u32 state;
2220 int ret;
2221
2222 ret = toshiba_usb_three_get(toshiba, &state);
2223 if (ret < 0)
2224 return ret;
2225
2226 return sprintf(buf, "%d\n", state);
2227}
2228
Azael Avalos9d309842015-02-10 23:43:59 -07002229static ssize_t usb_three_store(struct device *dev,
2230 struct device_attribute *attr,
2231 const char *buf, size_t count)
Azael Avalos17fe4b32015-02-10 21:09:20 -07002232{
2233 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
2234 int state;
2235 int ret;
2236
2237 ret = kstrtoint(buf, 0, &state);
2238 if (ret)
2239 return ret;
Darren Harte0769fe2015-02-11 20:50:08 -08002240 /*
2241 * Check for USB 3 mode where:
Azael Avalos17fe4b32015-02-10 21:09:20 -07002242 * 0 - Disabled (Acts like a USB 2 port, saving power)
2243 * 1 - Enabled
2244 */
2245 if (state != 0 && state != 1)
2246 return -EINVAL;
2247
2248 ret = toshiba_usb_three_set(toshiba, state);
2249 if (ret)
2250 return ret;
2251
2252 pr_info("Reboot for changes to USB 3 to take effect");
2253
2254 return count;
2255}
Azael Avalos0c3c0f12015-02-10 23:44:00 -07002256static DEVICE_ATTR_RW(usb_three);
Azael Avalos9bd12132015-02-10 23:43:58 -07002257
2258static struct attribute *toshiba_attributes[] = {
2259 &dev_attr_version.attr,
2260 &dev_attr_fan.attr,
2261 &dev_attr_kbd_backlight_mode.attr,
2262 &dev_attr_kbd_type.attr,
2263 &dev_attr_available_kbd_modes.attr,
2264 &dev_attr_kbd_backlight_timeout.attr,
2265 &dev_attr_touchpad.attr,
2266 &dev_attr_position.attr,
2267 &dev_attr_usb_sleep_charge.attr,
2268 &dev_attr_sleep_functions_on_battery.attr,
2269 &dev_attr_usb_rapid_charge.attr,
2270 &dev_attr_usb_sleep_music.attr,
2271 &dev_attr_kbd_function_keys.attr,
2272 &dev_attr_panel_power_on.attr,
2273 &dev_attr_usb_three.attr,
2274 NULL,
2275};
2276
Azael Avalos360f0f32014-03-25 20:38:31 -06002277static umode_t toshiba_sysfs_is_visible(struct kobject *kobj,
2278 struct attribute *attr, int idx)
2279{
2280 struct device *dev = container_of(kobj, struct device, kobj);
2281 struct toshiba_acpi_dev *drv = dev_get_drvdata(dev);
2282 bool exists = true;
2283
Azael Avalos94477d42015-02-10 21:09:17 -07002284 if (attr == &dev_attr_fan.attr)
2285 exists = (drv->fan_supported) ? true : false;
2286 else if (attr == &dev_attr_kbd_backlight_mode.attr)
Azael Avalos360f0f32014-03-25 20:38:31 -06002287 exists = (drv->kbd_illum_supported) ? true : false;
2288 else if (attr == &dev_attr_kbd_backlight_timeout.attr)
2289 exists = (drv->kbd_mode == SCI_KBD_MODE_AUTO) ? true : false;
Azael Avalos9d8658a2014-03-25 20:38:32 -06002290 else if (attr == &dev_attr_touchpad.attr)
2291 exists = (drv->touchpad_supported) ? true : false;
Azael Avalos5a2813e2014-03-25 20:38:34 -06002292 else if (attr == &dev_attr_position.attr)
2293 exists = (drv->accelerometer_supported) ? true : false;
Azael Avalose26ffe52015-01-18 18:30:22 -07002294 else if (attr == &dev_attr_usb_sleep_charge.attr)
2295 exists = (drv->usb_sleep_charge_supported) ? true : false;
Azael Avalos182bcaa2015-01-18 18:30:23 -07002296 else if (attr == &dev_attr_sleep_functions_on_battery.attr)
2297 exists = (drv->usb_sleep_charge_supported) ? true : false;
Azael Avalosbb3fe012015-01-18 18:30:24 -07002298 else if (attr == &dev_attr_usb_rapid_charge.attr)
2299 exists = (drv->usb_rapid_charge_supported) ? true : false;
Azael Avalos172ce0a2015-01-18 18:30:25 -07002300 else if (attr == &dev_attr_usb_sleep_music.attr)
2301 exists = (drv->usb_sleep_music_supported) ? true : false;
Azael Avalosbae84192015-02-10 21:09:18 -07002302 else if (attr == &dev_attr_kbd_function_keys.attr)
2303 exists = (drv->kbd_function_keys_supported) ? true : false;
Azael Avalos35d53ce2015-02-10 21:09:19 -07002304 else if (attr == &dev_attr_panel_power_on.attr)
2305 exists = (drv->panel_power_on_supported) ? true : false;
Azael Avalos17fe4b32015-02-10 21:09:20 -07002306 else if (attr == &dev_attr_usb_three.attr)
2307 exists = (drv->usb_three_supported) ? true : false;
Azael Avalos360f0f32014-03-25 20:38:31 -06002308
2309 return exists ? attr->mode : 0;
2310}
2311
Azael Avalos9bd12132015-02-10 23:43:58 -07002312static struct attribute_group toshiba_attr_group = {
2313 .is_visible = toshiba_sysfs_is_visible,
2314 .attrs = toshiba_attributes,
2315};
2316
Azael Avalos1f28f292014-12-04 20:22:45 -07002317/*
2318 * Hotkeys
2319 */
2320static int toshiba_acpi_enable_hotkeys(struct toshiba_acpi_dev *dev)
2321{
2322 acpi_status status;
2323 u32 result;
2324
2325 status = acpi_evaluate_object(dev->acpi_dev->handle,
2326 "ENAB", NULL, NULL);
2327 if (ACPI_FAILURE(status))
2328 return -ENODEV;
2329
2330 result = hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_ENABLE);
2331 if (result == TOS_FAILURE)
2332 return -EIO;
2333 else if (result == TOS_NOT_SUPPORTED)
2334 return -ENODEV;
2335
2336 return 0;
2337}
2338
Azael Avalosfb42d1f2015-03-20 16:55:18 -06002339static void toshiba_acpi_enable_special_functions(struct toshiba_acpi_dev *dev)
2340{
2341 u32 result;
2342
2343 /*
2344 * Re-activate the hotkeys, but this time, we are using the
2345 * "Special Functions" mode.
2346 */
2347 result = hci_write1(dev, HCI_HOTKEY_EVENT,
2348 HCI_HOTKEY_SPECIAL_FUNCTIONS);
2349 if (result != TOS_SUCCESS)
2350 pr_err("Could not enable the Special Function mode\n");
2351}
2352
Seth Forshee29cd2932012-01-18 13:44:09 -06002353static bool toshiba_acpi_i8042_filter(unsigned char data, unsigned char str,
2354 struct serio *port)
2355{
Giedrius Statkevičius98280372014-10-18 02:57:20 +03002356 if (str & I8042_STR_AUXDATA)
Seth Forshee29cd2932012-01-18 13:44:09 -06002357 return false;
2358
2359 if (unlikely(data == 0xe0))
2360 return false;
2361
2362 if ((data & 0x7f) == TOS1900_FN_SCAN) {
2363 schedule_work(&toshiba_acpi->hotkey_work);
2364 return true;
2365 }
2366
2367 return false;
2368}
2369
2370static void toshiba_acpi_hotkey_work(struct work_struct *work)
2371{
2372 acpi_handle ec_handle = ec_get_handle();
2373 acpi_status status;
2374
2375 if (!ec_handle)
2376 return;
2377
2378 status = acpi_evaluate_object(ec_handle, "NTFY", NULL, NULL);
2379 if (ACPI_FAILURE(status))
2380 pr_err("ACPI NTFY method execution failed\n");
2381}
2382
2383/*
2384 * Returns hotkey scancode, or < 0 on failure.
2385 */
2386static int toshiba_acpi_query_hotkey(struct toshiba_acpi_dev *dev)
2387{
Zhang Rui74facaf2013-09-03 08:32:15 +08002388 unsigned long long value;
Seth Forshee29cd2932012-01-18 13:44:09 -06002389 acpi_status status;
2390
Zhang Rui74facaf2013-09-03 08:32:15 +08002391 status = acpi_evaluate_integer(dev->acpi_dev->handle, "INFO",
2392 NULL, &value);
2393 if (ACPI_FAILURE(status)) {
Seth Forshee29cd2932012-01-18 13:44:09 -06002394 pr_err("ACPI INFO method execution failed\n");
2395 return -EIO;
2396 }
2397
Zhang Rui74facaf2013-09-03 08:32:15 +08002398 return value;
Seth Forshee29cd2932012-01-18 13:44:09 -06002399}
2400
2401static void toshiba_acpi_report_hotkey(struct toshiba_acpi_dev *dev,
2402 int scancode)
2403{
2404 if (scancode == 0x100)
2405 return;
2406
Darren Harte0769fe2015-02-11 20:50:08 -08002407 /* Act on key press; ignore key release */
Seth Forshee29cd2932012-01-18 13:44:09 -06002408 if (scancode & 0x80)
2409 return;
2410
2411 if (!sparse_keymap_report_event(dev->hotkey_dev, scancode, 1, true))
2412 pr_info("Unknown key %x\n", scancode);
2413}
2414
Azael Avalos71454d72014-12-04 20:22:46 -07002415static void toshiba_acpi_process_hotkeys(struct toshiba_acpi_dev *dev)
2416{
2417 u32 hci_result, value;
2418 int retries = 3;
2419 int scancode;
2420
2421 if (dev->info_supported) {
2422 scancode = toshiba_acpi_query_hotkey(dev);
2423 if (scancode < 0)
2424 pr_err("Failed to query hotkey event\n");
2425 else if (scancode != 0)
2426 toshiba_acpi_report_hotkey(dev, scancode);
2427 } else if (dev->system_event_supported) {
2428 do {
2429 hci_result = hci_read1(dev, HCI_SYSTEM_EVENT, &value);
2430 switch (hci_result) {
2431 case TOS_SUCCESS:
2432 toshiba_acpi_report_hotkey(dev, (int)value);
2433 break;
2434 case TOS_NOT_SUPPORTED:
2435 /*
2436 * This is a workaround for an unresolved
2437 * issue on some machines where system events
2438 * sporadically become disabled.
2439 */
2440 hci_result =
2441 hci_write1(dev, HCI_SYSTEM_EVENT, 1);
2442 pr_notice("Re-enabled hotkeys\n");
Darren Harte0769fe2015-02-11 20:50:08 -08002443 /* Fall through */
Azael Avalos71454d72014-12-04 20:22:46 -07002444 default:
2445 retries--;
2446 break;
2447 }
2448 } while (retries && hci_result != TOS_FIFO_EMPTY);
2449 }
2450}
2451
Greg Kroah-Hartmanb859f152012-12-21 13:18:33 -08002452static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
Matthew Garrett6335e4d2010-02-25 15:20:54 -05002453{
Takashi Iwaife808bfb2014-04-29 15:15:38 +02002454 const struct key_entry *keymap = toshiba_acpi_keymap;
Azael Avalosa2b34712015-03-20 16:55:17 -06002455 acpi_handle ec_handle;
2456 u32 events_type;
2457 u32 hci_result;
2458 int error;
2459
2460 error = toshiba_acpi_enable_hotkeys(dev);
2461 if (error)
2462 return error;
2463
2464 error = toshiba_hotkey_event_type_get(dev, &events_type);
2465 if (error) {
2466 pr_err("Unable to query Hotkey Event Type\n");
2467 return error;
2468 }
2469 dev->hotkey_event_type = events_type;
Seth Forshee135740d2011-09-20 16:55:49 -05002470
Seth Forshee135740d2011-09-20 16:55:49 -05002471 dev->hotkey_dev = input_allocate_device();
Joe Perchesb222cca2013-10-23 12:14:52 -07002472 if (!dev->hotkey_dev)
Seth Forshee135740d2011-09-20 16:55:49 -05002473 return -ENOMEM;
Seth Forshee135740d2011-09-20 16:55:49 -05002474
2475 dev->hotkey_dev->name = "Toshiba input device";
Seth Forshee6e02cc72011-09-20 16:55:51 -05002476 dev->hotkey_dev->phys = "toshiba_acpi/input0";
Seth Forshee135740d2011-09-20 16:55:49 -05002477 dev->hotkey_dev->id.bustype = BUS_HOST;
2478
Azael Avalosa2b34712015-03-20 16:55:17 -06002479 if (events_type == HCI_SYSTEM_TYPE1 ||
2480 !dev->kbd_function_keys_supported)
2481 keymap = toshiba_acpi_keymap;
2482 else if (events_type == HCI_SYSTEM_TYPE2 ||
2483 dev->kbd_function_keys_supported)
Takashi Iwaife808bfb2014-04-29 15:15:38 +02002484 keymap = toshiba_acpi_alt_keymap;
Azael Avalosa2b34712015-03-20 16:55:17 -06002485 else
2486 pr_info("Unknown event type received %x\n", events_type);
Takashi Iwaife808bfb2014-04-29 15:15:38 +02002487 error = sparse_keymap_setup(dev->hotkey_dev, keymap, NULL);
Seth Forshee135740d2011-09-20 16:55:49 -05002488 if (error)
2489 goto err_free_dev;
2490
Seth Forshee29cd2932012-01-18 13:44:09 -06002491 /*
2492 * For some machines the SCI responsible for providing hotkey
2493 * notification doesn't fire. We can trigger the notification
2494 * whenever the Fn key is pressed using the NTFY method, if
2495 * supported, so if it's present set up an i8042 key filter
2496 * for this purpose.
2497 */
Seth Forshee29cd2932012-01-18 13:44:09 -06002498 ec_handle = ec_get_handle();
Zhang Ruie2e19602013-09-03 08:32:06 +08002499 if (ec_handle && acpi_has_method(ec_handle, "NTFY")) {
Seth Forshee29cd2932012-01-18 13:44:09 -06002500 INIT_WORK(&dev->hotkey_work, toshiba_acpi_hotkey_work);
2501
2502 error = i8042_install_filter(toshiba_acpi_i8042_filter);
2503 if (error) {
2504 pr_err("Error installing key filter\n");
2505 goto err_free_keymap;
2506 }
2507
2508 dev->ntfy_supported = 1;
2509 }
2510
2511 /*
2512 * Determine hotkey query interface. Prefer using the INFO
2513 * method when it is available.
2514 */
Zhang Ruie2e19602013-09-03 08:32:06 +08002515 if (acpi_has_method(dev->acpi_dev->handle, "INFO"))
Seth Forshee29cd2932012-01-18 13:44:09 -06002516 dev->info_supported = 1;
Zhang Ruie2e19602013-09-03 08:32:06 +08002517 else {
Azael Avalos893f3f62014-09-29 20:40:09 -06002518 hci_result = hci_write1(dev, HCI_SYSTEM_EVENT, 1);
Azael Avalos1864bbc2014-09-29 20:40:08 -06002519 if (hci_result == TOS_SUCCESS)
Seth Forshee29cd2932012-01-18 13:44:09 -06002520 dev->system_event_supported = 1;
2521 }
2522
2523 if (!dev->info_supported && !dev->system_event_supported) {
2524 pr_warn("No hotkey query interface found\n");
2525 goto err_remove_filter;
2526 }
2527
Seth Forshee135740d2011-09-20 16:55:49 -05002528 error = input_register_device(dev->hotkey_dev);
2529 if (error) {
2530 pr_info("Unable to register input device\n");
Seth Forshee29cd2932012-01-18 13:44:09 -06002531 goto err_remove_filter;
Seth Forshee135740d2011-09-20 16:55:49 -05002532 }
2533
2534 return 0;
2535
Seth Forshee29cd2932012-01-18 13:44:09 -06002536 err_remove_filter:
2537 if (dev->ntfy_supported)
2538 i8042_remove_filter(toshiba_acpi_i8042_filter);
Seth Forshee135740d2011-09-20 16:55:49 -05002539 err_free_keymap:
2540 sparse_keymap_free(dev->hotkey_dev);
2541 err_free_dev:
2542 input_free_device(dev->hotkey_dev);
2543 dev->hotkey_dev = NULL;
2544 return error;
2545}
2546
Greg Kroah-Hartmanb859f152012-12-21 13:18:33 -08002547static int toshiba_acpi_setup_backlight(struct toshiba_acpi_dev *dev)
Seth Forshee62cce752012-04-19 11:23:50 -05002548{
2549 struct backlight_properties props;
2550 int brightness;
2551 int ret;
Akio Idehara121b7b02012-04-06 01:46:43 +09002552 bool enabled;
Seth Forshee62cce752012-04-19 11:23:50 -05002553
2554 /*
2555 * Some machines don't support the backlight methods at all, and
2556 * others support it read-only. Either of these is pretty useless,
2557 * so only register the backlight device if the backlight method
2558 * supports both reads and writes.
2559 */
2560 brightness = __get_lcd_brightness(dev);
2561 if (brightness < 0)
2562 return 0;
2563 ret = set_lcd_brightness(dev, brightness);
2564 if (ret) {
2565 pr_debug("Backlight method is read-only, disabling backlight support\n");
2566 return 0;
2567 }
2568
Akio Idehara121b7b02012-04-06 01:46:43 +09002569 /* Determine whether or not BIOS supports transflective backlight */
2570 ret = get_tr_backlight_status(dev, &enabled);
2571 dev->tr_backlight_supported = !ret;
2572
Matthew Garrett53039f22012-06-01 11:02:36 -04002573 memset(&props, 0, sizeof(props));
Seth Forshee62cce752012-04-19 11:23:50 -05002574 props.type = BACKLIGHT_PLATFORM;
2575 props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
Seth Forshee62cce752012-04-19 11:23:50 -05002576
Darren Harte0769fe2015-02-11 20:50:08 -08002577 /* Adding an extra level and having 0 change to transflective mode */
Akio Idehara121b7b02012-04-06 01:46:43 +09002578 if (dev->tr_backlight_supported)
2579 props.max_brightness++;
2580
Seth Forshee62cce752012-04-19 11:23:50 -05002581 dev->backlight_dev = backlight_device_register("toshiba",
2582 &dev->acpi_dev->dev,
2583 dev,
2584 &toshiba_backlight_data,
2585 &props);
2586 if (IS_ERR(dev->backlight_dev)) {
2587 ret = PTR_ERR(dev->backlight_dev);
2588 pr_err("Could not register toshiba backlight device\n");
2589 dev->backlight_dev = NULL;
2590 return ret;
2591 }
2592
2593 dev->backlight_dev->props.brightness = brightness;
2594 return 0;
2595}
2596
Rafael J. Wysocki51fac832013-01-24 00:24:48 +01002597static int toshiba_acpi_remove(struct acpi_device *acpi_dev)
Seth Forshee135740d2011-09-20 16:55:49 -05002598{
2599 struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
2600
Seth Forshee36d03f92011-09-20 16:55:53 -05002601 remove_toshiba_proc_entries(dev);
Matthew Garrettea6b31f2014-04-04 14:22:34 -04002602
Azael Avalos360f0f32014-03-25 20:38:31 -06002603 if (dev->sysfs_created)
2604 sysfs_remove_group(&dev->acpi_dev->dev.kobj,
2605 &toshiba_attr_group);
Seth Forshee135740d2011-09-20 16:55:49 -05002606
Seth Forshee29cd2932012-01-18 13:44:09 -06002607 if (dev->ntfy_supported) {
2608 i8042_remove_filter(toshiba_acpi_i8042_filter);
2609 cancel_work_sync(&dev->hotkey_work);
2610 }
2611
Seth Forshee135740d2011-09-20 16:55:49 -05002612 if (dev->hotkey_dev) {
2613 input_unregister_device(dev->hotkey_dev);
2614 sparse_keymap_free(dev->hotkey_dev);
2615 }
2616
2617 if (dev->bt_rfk) {
2618 rfkill_unregister(dev->bt_rfk);
2619 rfkill_destroy(dev->bt_rfk);
2620 }
2621
Markus Elfring00981812014-11-24 20:30:29 +01002622 backlight_device_unregister(dev->backlight_dev);
Seth Forshee135740d2011-09-20 16:55:49 -05002623
Seth Forshee36d03f92011-09-20 16:55:53 -05002624 if (dev->illumination_supported)
Seth Forshee135740d2011-09-20 16:55:49 -05002625 led_classdev_unregister(&dev->led_dev);
Matthew Garrettea6b31f2014-04-04 14:22:34 -04002626
Azael Avalos360f0f32014-03-25 20:38:31 -06002627 if (dev->kbd_led_registered)
2628 led_classdev_unregister(&dev->kbd_led);
Matthew Garrettea6b31f2014-04-04 14:22:34 -04002629
Azael Avalosdef6c4e2014-03-25 20:38:33 -06002630 if (dev->eco_supported)
2631 led_classdev_unregister(&dev->eco_led);
Seth Forshee135740d2011-09-20 16:55:49 -05002632
Seth Forshee29cd2932012-01-18 13:44:09 -06002633 if (toshiba_acpi)
2634 toshiba_acpi = NULL;
2635
Seth Forshee135740d2011-09-20 16:55:49 -05002636 kfree(dev);
2637
2638 return 0;
2639}
2640
Greg Kroah-Hartmanb859f152012-12-21 13:18:33 -08002641static const char *find_hci_method(acpi_handle handle)
Seth Forsheea540d6b2011-09-20 16:55:52 -05002642{
Zhang Ruie2e19602013-09-03 08:32:06 +08002643 if (acpi_has_method(handle, "GHCI"))
Seth Forsheea540d6b2011-09-20 16:55:52 -05002644 return "GHCI";
2645
Zhang Ruie2e19602013-09-03 08:32:06 +08002646 if (acpi_has_method(handle, "SPFC"))
Seth Forsheea540d6b2011-09-20 16:55:52 -05002647 return "SPFC";
2648
2649 return NULL;
2650}
2651
Greg Kroah-Hartmanb859f152012-12-21 13:18:33 -08002652static int toshiba_acpi_add(struct acpi_device *acpi_dev)
Seth Forshee135740d2011-09-20 16:55:49 -05002653{
2654 struct toshiba_acpi_dev *dev;
Seth Forsheea540d6b2011-09-20 16:55:52 -05002655 const char *hci_method;
Azael Avalosfb42d1f2015-03-20 16:55:18 -06002656 u32 special_functions;
Seth Forshee36d03f92011-09-20 16:55:53 -05002657 u32 dummy;
Seth Forshee135740d2011-09-20 16:55:49 -05002658 bool bt_present;
2659 int ret = 0;
Seth Forshee135740d2011-09-20 16:55:49 -05002660
Seth Forshee29cd2932012-01-18 13:44:09 -06002661 if (toshiba_acpi)
2662 return -EBUSY;
2663
Seth Forshee135740d2011-09-20 16:55:49 -05002664 pr_info("Toshiba Laptop ACPI Extras version %s\n",
2665 TOSHIBA_ACPI_VERSION);
2666
Seth Forsheea540d6b2011-09-20 16:55:52 -05002667 hci_method = find_hci_method(acpi_dev->handle);
2668 if (!hci_method) {
2669 pr_err("HCI interface not found\n");
Seth Forshee6e02cc72011-09-20 16:55:51 -05002670 return -ENODEV;
Seth Forsheea540d6b2011-09-20 16:55:52 -05002671 }
Seth Forshee6e02cc72011-09-20 16:55:51 -05002672
Seth Forshee135740d2011-09-20 16:55:49 -05002673 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
2674 if (!dev)
2675 return -ENOMEM;
2676 dev->acpi_dev = acpi_dev;
Seth Forsheea540d6b2011-09-20 16:55:52 -05002677 dev->method_hci = hci_method;
Seth Forshee135740d2011-09-20 16:55:49 -05002678 acpi_dev->driver_data = dev;
Azael Avalos360f0f32014-03-25 20:38:31 -06002679 dev_set_drvdata(&acpi_dev->dev, dev);
Seth Forshee135740d2011-09-20 16:55:49 -05002680
Azael Avalosa2b34712015-03-20 16:55:17 -06002681 /* Query the BIOS for supported features */
2682
2683 /*
2684 * The "Special Functions" are always supported by the laptops
2685 * with the new keyboard layout, query for its presence to help
2686 * determine the keymap layout to use.
2687 */
Azael Avalosfb42d1f2015-03-20 16:55:18 -06002688 ret = toshiba_function_keys_get(dev, &special_functions);
Azael Avalosa2b34712015-03-20 16:55:17 -06002689 dev->kbd_function_keys_supported = !ret;
2690
Seth Forshee6e02cc72011-09-20 16:55:51 -05002691 if (toshiba_acpi_setup_keyboard(dev))
2692 pr_info("Unable to activate hotkeys\n");
Seth Forshee135740d2011-09-20 16:55:49 -05002693
2694 mutex_init(&dev->mutex);
2695
Seth Forshee62cce752012-04-19 11:23:50 -05002696 ret = toshiba_acpi_setup_backlight(dev);
2697 if (ret)
Seth Forshee135740d2011-09-20 16:55:49 -05002698 goto error;
Seth Forshee135740d2011-09-20 16:55:49 -05002699
2700 /* Register rfkill switch for Bluetooth */
Azael Avalos1864bbc2014-09-29 20:40:08 -06002701 if (hci_get_bt_present(dev, &bt_present) == TOS_SUCCESS && bt_present) {
Seth Forshee135740d2011-09-20 16:55:49 -05002702 dev->bt_rfk = rfkill_alloc("Toshiba Bluetooth",
2703 &acpi_dev->dev,
2704 RFKILL_TYPE_BLUETOOTH,
2705 &toshiba_rfk_ops,
2706 dev);
2707 if (!dev->bt_rfk) {
2708 pr_err("unable to allocate rfkill device\n");
2709 ret = -ENOMEM;
2710 goto error;
2711 }
2712
2713 ret = rfkill_register(dev->bt_rfk);
2714 if (ret) {
2715 pr_err("unable to register rfkill device\n");
2716 rfkill_destroy(dev->bt_rfk);
2717 goto error;
2718 }
2719 }
2720
2721 if (toshiba_illumination_available(dev)) {
2722 dev->led_dev.name = "toshiba::illumination";
2723 dev->led_dev.max_brightness = 1;
2724 dev->led_dev.brightness_set = toshiba_illumination_set;
2725 dev->led_dev.brightness_get = toshiba_illumination_get;
2726 if (!led_classdev_register(&acpi_dev->dev, &dev->led_dev))
Seth Forshee36d03f92011-09-20 16:55:53 -05002727 dev->illumination_supported = 1;
Seth Forshee135740d2011-09-20 16:55:49 -05002728 }
Matthew Garrettea6b31f2014-04-04 14:22:34 -04002729
Azael Avalosdef6c4e2014-03-25 20:38:33 -06002730 if (toshiba_eco_mode_available(dev)) {
2731 dev->eco_led.name = "toshiba::eco_mode";
2732 dev->eco_led.max_brightness = 1;
2733 dev->eco_led.brightness_set = toshiba_eco_mode_set_status;
2734 dev->eco_led.brightness_get = toshiba_eco_mode_get_status;
2735 if (!led_classdev_register(&dev->acpi_dev->dev, &dev->eco_led))
2736 dev->eco_supported = 1;
2737 }
Matthew Garrettea6b31f2014-04-04 14:22:34 -04002738
Azael Avalos93f8c162014-09-12 18:50:36 -06002739 dev->kbd_illum_supported = toshiba_kbd_illum_available(dev);
Azael Avalos360f0f32014-03-25 20:38:31 -06002740 /*
2741 * Only register the LED if KBD illumination is supported
2742 * and the keyboard backlight operation mode is set to FN-Z
2743 */
2744 if (dev->kbd_illum_supported && dev->kbd_mode == SCI_KBD_MODE_FNZ) {
2745 dev->kbd_led.name = "toshiba::kbd_backlight";
2746 dev->kbd_led.max_brightness = 1;
2747 dev->kbd_led.brightness_set = toshiba_kbd_backlight_set;
2748 dev->kbd_led.brightness_get = toshiba_kbd_backlight_get;
2749 if (!led_classdev_register(&dev->acpi_dev->dev, &dev->kbd_led))
2750 dev->kbd_led_registered = 1;
2751 }
Matthew Garrettea6b31f2014-04-04 14:22:34 -04002752
Azael Avalos9d8658a2014-03-25 20:38:32 -06002753 ret = toshiba_touchpad_get(dev, &dummy);
2754 dev->touchpad_supported = !ret;
Matthew Garrettea6b31f2014-04-04 14:22:34 -04002755
Azael Avalos5a2813e2014-03-25 20:38:34 -06002756 ret = toshiba_accelerometer_supported(dev);
2757 dev->accelerometer_supported = !ret;
Seth Forshee135740d2011-09-20 16:55:49 -05002758
Azael Avalose26ffe52015-01-18 18:30:22 -07002759 ret = toshiba_usb_sleep_charge_get(dev, &dummy);
2760 dev->usb_sleep_charge_supported = !ret;
2761
Azael Avalosbb3fe012015-01-18 18:30:24 -07002762 ret = toshiba_usb_rapid_charge_get(dev, &dummy);
2763 dev->usb_rapid_charge_supported = !ret;
2764
Azael Avalos172ce0a2015-01-18 18:30:25 -07002765 ret = toshiba_usb_sleep_music_get(dev, &dummy);
2766 dev->usb_sleep_music_supported = !ret;
2767
Azael Avalos35d53ce2015-02-10 21:09:19 -07002768 ret = toshiba_panel_power_on_get(dev, &dummy);
2769 dev->panel_power_on_supported = !ret;
2770
Azael Avalos17fe4b32015-02-10 21:09:20 -07002771 ret = toshiba_usb_three_get(dev, &dummy);
2772 dev->usb_three_supported = !ret;
2773
Seth Forshee36d03f92011-09-20 16:55:53 -05002774 ret = get_video_status(dev, &dummy);
2775 dev->video_supported = !ret;
2776
2777 ret = get_fan_status(dev, &dummy);
2778 dev->fan_supported = !ret;
2779
Azael Avalosfb42d1f2015-03-20 16:55:18 -06002780 /*
2781 * Enable the "Special Functions" mode only if they are
2782 * supported and if they are activated.
2783 */
2784 if (dev->kbd_function_keys_supported && special_functions)
2785 toshiba_acpi_enable_special_functions(dev);
2786
Azael Avalos360f0f32014-03-25 20:38:31 -06002787 ret = sysfs_create_group(&dev->acpi_dev->dev.kobj,
2788 &toshiba_attr_group);
2789 if (ret) {
2790 dev->sysfs_created = 0;
2791 goto error;
2792 }
2793 dev->sysfs_created = !ret;
2794
Seth Forshee36d03f92011-09-20 16:55:53 -05002795 create_toshiba_proc_entries(dev);
2796
Seth Forshee29cd2932012-01-18 13:44:09 -06002797 toshiba_acpi = dev;
2798
Seth Forshee135740d2011-09-20 16:55:49 -05002799 return 0;
2800
2801error:
Rafael J. Wysocki51fac832013-01-24 00:24:48 +01002802 toshiba_acpi_remove(acpi_dev);
Seth Forshee135740d2011-09-20 16:55:49 -05002803 return ret;
2804}
2805
2806static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event)
2807{
2808 struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
Azael Avalos80546902014-12-04 20:22:47 -07002809 int ret;
Matthew Garrett6335e4d2010-02-25 15:20:54 -05002810
Azael Avalos71454d72014-12-04 20:22:46 -07002811 switch (event) {
2812 case 0x80: /* Hotkeys and some system events */
2813 toshiba_acpi_process_hotkeys(dev);
2814 break;
Azael Avalosbab09e22015-03-06 18:14:41 -07002815 case 0x81: /* Dock events */
2816 case 0x82:
2817 case 0x83:
2818 pr_info("Dock event received %x\n", event);
2819 break;
2820 case 0x88: /* Thermal events */
2821 pr_info("Thermal event received\n");
2822 break;
2823 case 0x8f: /* LID closed */
2824 case 0x90: /* LID is closed and Dock has been ejected */
2825 break;
2826 case 0x8c: /* SATA power events */
2827 case 0x8b:
2828 pr_info("SATA power event received %x\n", event);
2829 break;
Azael Avalos80546902014-12-04 20:22:47 -07002830 case 0x92: /* Keyboard backlight mode changed */
2831 /* Update sysfs entries */
2832 ret = sysfs_update_group(&acpi_dev->dev.kobj,
2833 &toshiba_attr_group);
2834 if (ret)
2835 pr_err("Unable to update sysfs entries\n");
2836 break;
Azael Avalosbab09e22015-03-06 18:14:41 -07002837 case 0x85: /* Unknown */
2838 case 0x8d: /* Unknown */
Azael Avalos71454d72014-12-04 20:22:46 -07002839 case 0x8e: /* Unknown */
Azael Avalosbab09e22015-03-06 18:14:41 -07002840 case 0x94: /* Unknown */
2841 case 0x95: /* Unknown */
Azael Avalos71454d72014-12-04 20:22:46 -07002842 default:
2843 pr_info("Unknown event received %x\n", event);
2844 break;
Seth Forshee29cd2932012-01-18 13:44:09 -06002845 }
Azael Avalosbab09e22015-03-06 18:14:41 -07002846
2847 acpi_bus_generate_netlink_event(acpi_dev->pnp.device_class,
2848 dev_name(&acpi_dev->dev),
2849 event, 0);
Matthew Garrett6335e4d2010-02-25 15:20:54 -05002850}
2851
Rafael J. Wysocki3567a4e22012-08-09 23:00:13 +02002852#ifdef CONFIG_PM_SLEEP
Rafael J. Wysocki43d2fd32012-06-27 23:27:16 +02002853static int toshiba_acpi_suspend(struct device *device)
Seth Forshee29cd2932012-01-18 13:44:09 -06002854{
Rafael J. Wysocki43d2fd32012-06-27 23:27:16 +02002855 struct toshiba_acpi_dev *dev = acpi_driver_data(to_acpi_device(device));
Seth Forshee29cd2932012-01-18 13:44:09 -06002856 u32 result;
2857
2858 if (dev->hotkey_dev)
Azael Avalos893f3f62014-09-29 20:40:09 -06002859 result = hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_DISABLE);
Seth Forshee29cd2932012-01-18 13:44:09 -06002860
2861 return 0;
2862}
2863
Rafael J. Wysocki43d2fd32012-06-27 23:27:16 +02002864static int toshiba_acpi_resume(struct device *device)
Seth Forshee29cd2932012-01-18 13:44:09 -06002865{
Rafael J. Wysocki43d2fd32012-06-27 23:27:16 +02002866 struct toshiba_acpi_dev *dev = acpi_driver_data(to_acpi_device(device));
Azael Avalos1f28f292014-12-04 20:22:45 -07002867 int error;
Seth Forshee29cd2932012-01-18 13:44:09 -06002868
Benjamin Tissoirese7fdb762014-09-02 14:04:19 -04002869 if (dev->hotkey_dev) {
Azael Avalos1f28f292014-12-04 20:22:45 -07002870 error = toshiba_acpi_enable_hotkeys(dev);
2871 if (error)
Benjamin Tissoirese7fdb762014-09-02 14:04:19 -04002872 pr_info("Unable to re-enable hotkeys\n");
Benjamin Tissoirese7fdb762014-09-02 14:04:19 -04002873 }
Seth Forshee29cd2932012-01-18 13:44:09 -06002874
2875 return 0;
2876}
Rafael J. Wysocki3567a4e22012-08-09 23:00:13 +02002877#endif
Matthew Garrett6335e4d2010-02-25 15:20:54 -05002878
Rafael J. Wysocki43d2fd32012-06-27 23:27:16 +02002879static SIMPLE_DEV_PM_OPS(toshiba_acpi_pm,
2880 toshiba_acpi_suspend, toshiba_acpi_resume);
2881
Seth Forshee135740d2011-09-20 16:55:49 -05002882static struct acpi_driver toshiba_acpi_driver = {
2883 .name = "Toshiba ACPI driver",
2884 .owner = THIS_MODULE,
2885 .ids = toshiba_device_ids,
2886 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
2887 .ops = {
2888 .add = toshiba_acpi_add,
2889 .remove = toshiba_acpi_remove,
2890 .notify = toshiba_acpi_notify,
2891 },
Rafael J. Wysocki43d2fd32012-06-27 23:27:16 +02002892 .drv.pm = &toshiba_acpi_pm,
Seth Forshee135740d2011-09-20 16:55:49 -05002893};
Holger Machtc9263552006-10-20 14:30:29 -07002894
Len Brown4be44fc2005-08-05 00:44:28 -04002895static int __init toshiba_acpi_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002896{
Seth Forshee135740d2011-09-20 16:55:49 -05002897 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002898
Seth Forsheef11f9992012-01-18 13:44:11 -06002899 /*
2900 * Machines with this WMI guid aren't supported due to bugs in
2901 * their AML. This check relies on wmi initializing before
2902 * toshiba_acpi to guarantee guids have been identified.
2903 */
2904 if (wmi_has_guid(TOSHIBA_WMI_EVENT_GUID))
2905 return -ENODEV;
2906
Linus Torvalds1da177e2005-04-16 15:20:36 -07002907 toshiba_proc_dir = proc_mkdir(PROC_TOSHIBA, acpi_root_dir);
2908 if (!toshiba_proc_dir) {
Seth Forshee135740d2011-09-20 16:55:49 -05002909 pr_err("Unable to create proc dir " PROC_TOSHIBA "\n");
philipl@overt.orgc41a40c2008-08-30 11:57:39 -04002910 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002911 }
2912
Seth Forshee135740d2011-09-20 16:55:49 -05002913 ret = acpi_bus_register_driver(&toshiba_acpi_driver);
2914 if (ret) {
2915 pr_err("Failed to register ACPI driver: %d\n", ret);
2916 remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
Holger Machtc9263552006-10-20 14:30:29 -07002917 }
2918
Seth Forshee135740d2011-09-20 16:55:49 -05002919 return ret;
2920}
philipl@overt.orgc41a40c2008-08-30 11:57:39 -04002921
Seth Forshee135740d2011-09-20 16:55:49 -05002922static void __exit toshiba_acpi_exit(void)
2923{
2924 acpi_bus_unregister_driver(&toshiba_acpi_driver);
2925 if (toshiba_proc_dir)
2926 remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002927}
2928
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929module_init(toshiba_acpi_init);
2930module_exit(toshiba_acpi_exit);