toshiba_acpi.c 31.4 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5
/*
 *  toshiba_acpi.c - Toshiba Laptop ACPI Extras
 *
 *
 *  Copyright (C) 2002-2004 John Belmonte
6
 *  Copyright (C) 2008 Philip Langdale
7
 *  Copyright (C) 2010 Pierre Ducroquet
L
Linus Torvalds 已提交
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *
 *  The devolpment page for this driver is located at
 *  http://memebeam.org/toys/ToshibaAcpiDriver.
 *
 *  Credits:
 *	Jonathan A. Buzzard - Toshiba HCI info, and critical tips on reverse
 *		engineering the Windows drivers
 *	Yasushi Nagato - changes for linux kernel 2.4 -> 2.5
 *	Rob Miller - TV out and hotkeys help
 *
 *
 *  TODO
 *
 */

38 39
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

40
#define TOSHIBA_ACPI_VERSION	"0.19"
L
Linus Torvalds 已提交
41 42 43 44 45 46 47
#define PROC_INTERFACE_VERSION	1

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
48
#include <linux/seq_file.h>
49
#include <linux/backlight.h>
50
#include <linux/rfkill.h>
51
#include <linux/input.h>
52
#include <linux/input/sparse-keymap.h>
53
#include <linux/leds.h>
54
#include <linux/slab.h>
55 56
#include <linux/workqueue.h>
#include <linux/i8042.h>
57

L
Linus Torvalds 已提交
58 59 60 61 62 63 64 65
#include <asm/uaccess.h>

#include <acpi/acpi_drivers.h>

MODULE_AUTHOR("John Belmonte");
MODULE_DESCRIPTION("Toshiba Laptop ACPI Extras Driver");
MODULE_LICENSE("GPL");

66 67
#define TOSHIBA_WMI_EVENT_GUID "59142400-C6A3-40FA-BADB-8A2652834100"

68 69 70
/* Scan code for Fn key on TOS1900 models */
#define TOS1900_FN_SCAN		0x6e

L
Linus Torvalds 已提交
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
/* Toshiba ACPI method paths */
#define METHOD_VIDEO_OUT	"\\_SB_.VALX.DSSX"

/* Toshiba HCI interface definitions
 *
 * HCI is Toshiba's "Hardware Control Interface" which is supposed to
 * be uniform across all their models.  Ideally we would just call
 * dedicated ACPI methods instead of using this primitive interface.
 * However the ACPI methods seem to be incomplete in some areas (for
 * example they allow setting, but not reading, the LCD brightness value),
 * so this is still useful.
 */

#define HCI_WORDS			6

/* operations */
#define HCI_SET				0xff00
#define HCI_GET				0xfe00

/* return codes */
#define HCI_SUCCESS			0x0000
#define HCI_FAILURE			0x1000
#define HCI_NOT_SUPPORTED		0x8000
#define HCI_EMPTY			0x8c00

/* registers */
#define HCI_FAN				0x0004
#define HCI_SYSTEM_EVENT		0x0016
#define HCI_VIDEO_OUT			0x001c
#define HCI_HOTKEY_EVENT		0x001e
#define HCI_LCD_BRIGHTNESS		0x002a
102
#define HCI_WIRELESS			0x0056
L
Linus Torvalds 已提交
103 104

/* field definitions */
105 106
#define HCI_HOTKEY_DISABLE		0x0b
#define HCI_HOTKEY_ENABLE		0x09
L
Linus Torvalds 已提交
107 108 109 110 111 112
#define HCI_LCD_BRIGHTNESS_BITS		3
#define HCI_LCD_BRIGHTNESS_SHIFT	(16-HCI_LCD_BRIGHTNESS_BITS)
#define HCI_LCD_BRIGHTNESS_LEVELS	(1 << HCI_LCD_BRIGHTNESS_BITS)
#define HCI_VIDEO_OUT_LCD		0x1
#define HCI_VIDEO_OUT_CRT		0x2
#define HCI_VIDEO_OUT_TV		0x4
113 114 115 116
#define HCI_WIRELESS_KILL_SWITCH	0x01
#define HCI_WIRELESS_BT_PRESENT		0x0f
#define HCI_WIRELESS_BT_ATTACH		0x40
#define HCI_WIRELESS_BT_POWER		0x80
L
Linus Torvalds 已提交
117

118 119 120 121 122
struct toshiba_acpi_dev {
	struct acpi_device *acpi_dev;
	const char *method_hci;
	struct rfkill *bt_rfk;
	struct input_dev *hotkey_dev;
123
	struct work_struct hotkey_work;
124 125
	struct backlight_device *backlight_dev;
	struct led_classdev led_dev;
126

127 128 129 130
	int force_fan;
	int last_key_event;
	int key_event_valid;

131 132 133 134
	unsigned int illumination_supported:1;
	unsigned int video_supported:1;
	unsigned int fan_supported:1;
	unsigned int system_event_supported:1;
135 136
	unsigned int ntfy_supported:1;
	unsigned int info_supported:1;
137

138 139 140
	struct mutex mutex;
};

141 142
static struct toshiba_acpi_dev *toshiba_acpi;

143 144
static const struct acpi_device_id toshiba_device_ids[] = {
	{"TOS6200", 0},
145
	{"TOS6208", 0},
146 147 148 149 150
	{"TOS1900", 0},
	{"", 0},
};
MODULE_DEVICE_TABLE(acpi, toshiba_device_ids);

151
static const struct key_entry toshiba_acpi_keymap[] __devinitconst = {
152 153 154
	{ KE_KEY, 0x101, { KEY_MUTE } },
	{ KE_KEY, 0x102, { KEY_ZOOMOUT } },
	{ KE_KEY, 0x103, { KEY_ZOOMIN } },
155 156
	{ KE_KEY, 0x12c, { KEY_KBDILLUMTOGGLE } },
	{ KE_KEY, 0x139, { KEY_ZOOMRESET } },
157 158 159 160 161 162 163 164
	{ KE_KEY, 0x13b, { KEY_COFFEE } },
	{ KE_KEY, 0x13c, { KEY_BATTERY } },
	{ KE_KEY, 0x13d, { KEY_SLEEP } },
	{ KE_KEY, 0x13e, { KEY_SUSPEND } },
	{ KE_KEY, 0x13f, { KEY_SWITCHVIDEOMODE } },
	{ KE_KEY, 0x140, { KEY_BRIGHTNESSDOWN } },
	{ KE_KEY, 0x141, { KEY_BRIGHTNESSUP } },
	{ KE_KEY, 0x142, { KEY_WLAN } },
165
	{ KE_KEY, 0x143, { KEY_TOUCHPAD_TOGGLE } },
166
	{ KE_KEY, 0x17f, { KEY_FN } },
167 168 169 170 171 172 173 174
	{ KE_KEY, 0xb05, { KEY_PROG2 } },
	{ KE_KEY, 0xb06, { KEY_WWW } },
	{ KE_KEY, 0xb07, { KEY_MAIL } },
	{ KE_KEY, 0xb30, { KEY_STOP } },
	{ KE_KEY, 0xb31, { KEY_PREVIOUSSONG } },
	{ KE_KEY, 0xb32, { KEY_NEXTSONG } },
	{ KE_KEY, 0xb33, { KEY_PLAYPAUSE } },
	{ KE_KEY, 0xb5a, { KEY_MEDIA } },
175
	{ KE_IGNORE, 0x1430, { KEY_RESERVED } },
176
	{ KE_END, 0 },
177 178
};

L
Linus Torvalds 已提交
179 180 181
/* utility
 */

L
Len Brown 已提交
182
static __inline__ void _set_bit(u32 * word, u32 mask, int value)
L
Linus Torvalds 已提交
183 184 185 186 187 188 189
{
	*word = (*word & ~mask) | (mask * value);
}

/* acpi interface wrappers
 */

L
Len Brown 已提交
190
static int write_acpi_int(const char *methodName, int val)
L
Linus Torvalds 已提交
191 192 193 194 195
{
	struct acpi_object_list params;
	union acpi_object in_objs[1];
	acpi_status status;

196
	params.count = ARRAY_SIZE(in_objs);
L
Linus Torvalds 已提交
197 198 199 200
	params.pointer = in_objs;
	in_objs[0].type = ACPI_TYPE_INTEGER;
	in_objs[0].integer.value = val;

L
Len Brown 已提交
201
	status = acpi_evaluate_object(NULL, (char *)methodName, &params, NULL);
S
Seth Forshee 已提交
202
	return (status == AE_OK) ? 0 : -EIO;
L
Linus Torvalds 已提交
203 204 205 206 207
}

/* Perform a raw HCI call.  Here we don't care about input or output buffer
 * format.
 */
208 209
static acpi_status hci_raw(struct toshiba_acpi_dev *dev,
			   const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
L
Linus Torvalds 已提交
210 211 212 213
{
	struct acpi_object_list params;
	union acpi_object in_objs[HCI_WORDS];
	struct acpi_buffer results;
L
Len Brown 已提交
214
	union acpi_object out_objs[HCI_WORDS + 1];
L
Linus Torvalds 已提交
215 216 217 218 219 220 221 222 223 224 225 226 227
	acpi_status status;
	int i;

	params.count = HCI_WORDS;
	params.pointer = in_objs;
	for (i = 0; i < HCI_WORDS; ++i) {
		in_objs[i].type = ACPI_TYPE_INTEGER;
		in_objs[i].integer.value = in[i];
	}

	results.length = sizeof(out_objs);
	results.pointer = out_objs;

228 229
	status = acpi_evaluate_object(dev->acpi_dev->handle,
				      (char *)dev->method_hci, &params,
L
Len Brown 已提交
230
				      &results);
L
Linus Torvalds 已提交
231 232 233 234 235 236 237 238 239
	if ((status == AE_OK) && (out_objs->package.count <= HCI_WORDS)) {
		for (i = 0; i < out_objs->package.count; ++i) {
			out[i] = out_objs->package.elements[i].integer.value;
		}
	}

	return status;
}

240
/* common hci tasks (get or set one or two value)
L
Linus Torvalds 已提交
241 242 243 244 245
 *
 * In addition to the ACPI status, the HCI system returns a result which
 * may be useful (such as "not supported").
 */

246 247
static acpi_status hci_write1(struct toshiba_acpi_dev *dev, u32 reg,
			      u32 in1, u32 *result)
L
Linus Torvalds 已提交
248 249 250
{
	u32 in[HCI_WORDS] = { HCI_SET, reg, in1, 0, 0, 0 };
	u32 out[HCI_WORDS];
251
	acpi_status status = hci_raw(dev, in, out);
L
Linus Torvalds 已提交
252 253 254 255
	*result = (status == AE_OK) ? out[0] : HCI_FAILURE;
	return status;
}

256 257
static acpi_status hci_read1(struct toshiba_acpi_dev *dev, u32 reg,
			     u32 *out1, u32 *result)
L
Linus Torvalds 已提交
258 259 260
{
	u32 in[HCI_WORDS] = { HCI_GET, reg, 0, 0, 0, 0 };
	u32 out[HCI_WORDS];
261
	acpi_status status = hci_raw(dev, in, out);
L
Linus Torvalds 已提交
262 263 264 265 266
	*out1 = out[2];
	*result = (status == AE_OK) ? out[0] : HCI_FAILURE;
	return status;
}

267 268
static acpi_status hci_write2(struct toshiba_acpi_dev *dev, u32 reg,
			      u32 in1, u32 in2, u32 *result)
269 270 271
{
	u32 in[HCI_WORDS] = { HCI_SET, reg, in1, in2, 0, 0 };
	u32 out[HCI_WORDS];
272
	acpi_status status = hci_raw(dev, in, out);
273 274 275 276
	*result = (status == AE_OK) ? out[0] : HCI_FAILURE;
	return status;
}

277 278
static acpi_status hci_read2(struct toshiba_acpi_dev *dev, u32 reg,
			     u32 *out1, u32 *out2, u32 *result)
279 280 281
{
	u32 in[HCI_WORDS] = { HCI_GET, reg, *out1, *out2, 0, 0 };
	u32 out[HCI_WORDS];
282
	acpi_status status = hci_raw(dev, in, out);
283 284 285 286 287 288
	*out1 = out[2];
	*out2 = out[3];
	*result = (status == AE_OK) ? out[0] : HCI_FAILURE;
	return status;
}

289
/* Illumination support */
290
static int toshiba_illumination_available(struct toshiba_acpi_dev *dev)
291 292 293 294 295 296
{
	u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
	u32 out[HCI_WORDS];
	acpi_status status;

	in[0] = 0xf100;
297
	status = hci_raw(dev, in, out);
298
	if (ACPI_FAILURE(status)) {
299
		pr_info("Illumination device not available\n");
300 301 302
		return 0;
	}
	in[0] = 0xf400;
303
	status = hci_raw(dev, in, out);
304 305 306 307 308 309
	return 1;
}

static void toshiba_illumination_set(struct led_classdev *cdev,
				     enum led_brightness brightness)
{
310 311
	struct toshiba_acpi_dev *dev = container_of(cdev,
			struct toshiba_acpi_dev, led_dev);
312 313 314 315 316 317
	u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
	u32 out[HCI_WORDS];
	acpi_status status;

	/* First request : initialize communication. */
	in[0] = 0xf100;
318
	status = hci_raw(dev, in, out);
319
	if (ACPI_FAILURE(status)) {
320
		pr_info("Illumination device not available\n");
321 322 323 324 325 326 327 328
		return;
	}

	if (brightness) {
		/* Switch the illumination on */
		in[0] = 0xf400;
		in[1] = 0x14e;
		in[2] = 1;
329
		status = hci_raw(dev, in, out);
330
		if (ACPI_FAILURE(status)) {
331
			pr_info("ACPI call for illumination failed\n");
332 333 334 335 336 337 338
			return;
		}
	} else {
		/* Switch the illumination off */
		in[0] = 0xf400;
		in[1] = 0x14e;
		in[2] = 0;
339
		status = hci_raw(dev, in, out);
340
		if (ACPI_FAILURE(status)) {
341
			pr_info("ACPI call for illumination failed.\n");
342 343 344 345 346 347 348 349
			return;
		}
	}

	/* Last request : close communication. */
	in[0] = 0xf200;
	in[1] = 0;
	in[2] = 0;
350
	hci_raw(dev, in, out);
351 352 353 354
}

static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev)
{
355 356
	struct toshiba_acpi_dev *dev = container_of(cdev,
			struct toshiba_acpi_dev, led_dev);
357 358 359 360 361 362 363
	u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
	u32 out[HCI_WORDS];
	acpi_status status;
	enum led_brightness result;

	/* First request : initialize communication. */
	in[0] = 0xf100;
364
	status = hci_raw(dev, in, out);
365
	if (ACPI_FAILURE(status)) {
366
		pr_info("Illumination device not available\n");
367 368 369 370 371 372
		return LED_OFF;
	}

	/* Check the illumination */
	in[0] = 0xf300;
	in[1] = 0x14e;
373
	status = hci_raw(dev, in, out);
374
	if (ACPI_FAILURE(status)) {
375
		pr_info("ACPI call for illumination failed.\n");
376 377 378 379 380 381 382 383 384
		return LED_OFF;
	}

	result = out[2] ? LED_FULL : LED_OFF;

	/* Last request : close communication. */
	in[0] = 0xf200;
	in[1] = 0;
	in[2] = 0;
385
	hci_raw(dev, in, out);
386 387 388 389

	return result;
}

390 391
/* Bluetooth rfkill handlers */

392
static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present)
393 394 395 396 397 398
{
	u32 hci_result;
	u32 value, value2;

	value = 0;
	value2 = 0;
399
	hci_read2(dev, HCI_WIRELESS, &value, &value2, &hci_result);
400 401 402 403 404 405
	if (hci_result == HCI_SUCCESS)
		*present = (value & HCI_WIRELESS_BT_PRESENT) ? true : false;

	return hci_result;
}

406
static u32 hci_get_radio_state(struct toshiba_acpi_dev *dev, bool *radio_state)
407 408 409 410 411 412
{
	u32 hci_result;
	u32 value, value2;

	value = 0;
	value2 = 0x0001;
413
	hci_read2(dev, HCI_WIRELESS, &value, &value2, &hci_result);
414 415 416 417 418

	*radio_state = value & HCI_WIRELESS_KILL_SWITCH;
	return hci_result;
}

J
Johannes Berg 已提交
419
static int bt_rfkill_set_block(void *data, bool blocked)
420
{
J
Johannes Berg 已提交
421
	struct toshiba_acpi_dev *dev = data;
422 423
	u32 result1, result2;
	u32 value;
J
Johannes Berg 已提交
424
	int err;
425 426
	bool radio_state;

J
Johannes Berg 已提交
427
	value = (blocked == false);
428

J
Johannes Berg 已提交
429
	mutex_lock(&dev->mutex);
430
	if (hci_get_radio_state(dev, &radio_state) != HCI_SUCCESS) {
S
Seth Forshee 已提交
431
		err = -EIO;
J
Johannes Berg 已提交
432 433
		goto out;
	}
434

J
Johannes Berg 已提交
435 436 437
	if (!radio_state) {
		err = 0;
		goto out;
438 439
	}

440 441
	hci_write2(dev, HCI_WIRELESS, value, HCI_WIRELESS_BT_POWER, &result1);
	hci_write2(dev, HCI_WIRELESS, value, HCI_WIRELESS_BT_ATTACH, &result2);
442 443

	if (result1 != HCI_SUCCESS || result2 != HCI_SUCCESS)
S
Seth Forshee 已提交
444
		err = -EIO;
J
Johannes Berg 已提交
445 446 447 448 449
	else
		err = 0;
 out:
	mutex_unlock(&dev->mutex);
	return err;
450 451
}

J
Johannes Berg 已提交
452
static void bt_rfkill_poll(struct rfkill *rfkill, void *data)
453 454 455 456
{
	bool new_rfk_state;
	bool value;
	u32 hci_result;
J
Johannes Berg 已提交
457 458 459
	struct toshiba_acpi_dev *dev = data;

	mutex_lock(&dev->mutex);
460

461
	hci_result = hci_get_radio_state(dev, &value);
J
Johannes Berg 已提交
462 463 464
	if (hci_result != HCI_SUCCESS) {
		/* Can't do anything useful */
		mutex_unlock(&dev->mutex);
J
Jiri Slaby 已提交
465
		return;
J
Johannes Berg 已提交
466
	}
467 468 469 470 471

	new_rfk_state = value;

	mutex_unlock(&dev->mutex);

J
Johannes Berg 已提交
472 473
	if (rfkill_set_hw_state(rfkill, !new_rfk_state))
		bt_rfkill_set_block(data, true);
474 475
}

J
Johannes Berg 已提交
476 477 478 479 480
static const struct rfkill_ops toshiba_rfk_ops = {
	.set_block = bt_rfkill_set_block,
	.poll = bt_rfkill_poll,
};

L
Len Brown 已提交
481
static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ;
L
Linus Torvalds 已提交
482

483
static int get_lcd(struct backlight_device *bd)
L
Linus Torvalds 已提交
484
{
485
	struct toshiba_acpi_dev *dev = bl_get_data(bd);
L
Linus Torvalds 已提交
486 487 488
	u32 hci_result;
	u32 value;

489
	hci_read1(dev, HCI_LCD_BRIGHTNESS, &value, &hci_result);
S
Seth Forshee 已提交
490
	if (hci_result == HCI_SUCCESS)
491
		return (value >> HCI_LCD_BRIGHTNESS_SHIFT);
S
Seth Forshee 已提交
492 493

	return -EIO;
494 495
}

496
static int lcd_proc_show(struct seq_file *m, void *v)
497
{
498 499 500 501 502
	struct toshiba_acpi_dev *dev = m->private;
	int value;

	if (!dev->backlight_dev)
		return -ENODEV;
503

504
	value = get_lcd(dev->backlight_dev);
505
	if (value >= 0) {
506 507
		seq_printf(m, "brightness:              %d\n", value);
		seq_printf(m, "brightness_levels:       %d\n",
L
Len Brown 已提交
508
			     HCI_LCD_BRIGHTNESS_LEVELS);
S
Seth Forshee 已提交
509
		return 0;
L
Linus Torvalds 已提交
510 511
	}

S
Seth Forshee 已提交
512 513
	pr_err("Error reading LCD brightness\n");
	return -EIO;
514 515 516 517
}

static int lcd_proc_open(struct inode *inode, struct file *file)
{
518
	return single_open(file, lcd_proc_show, PDE(inode)->data);
L
Linus Torvalds 已提交
519 520
}

521
static int set_lcd(struct toshiba_acpi_dev *dev, int value)
522 523 524 525
{
	u32 hci_result;

	value = value << HCI_LCD_BRIGHTNESS_SHIFT;
526
	hci_write1(dev, HCI_LCD_BRIGHTNESS, value, &hci_result);
S
Seth Forshee 已提交
527
	return hci_result == HCI_SUCCESS ? 0 : -EIO;
528 529 530 531
}

static int set_lcd_status(struct backlight_device *bd)
{
532 533
	struct toshiba_acpi_dev *dev = bl_get_data(bd);
	return set_lcd(dev, bd->props.brightness);
534 535
}

536 537
static ssize_t lcd_proc_write(struct file *file, const char __user *buf,
			      size_t count, loff_t *pos)
L
Linus Torvalds 已提交
538
{
539
	struct toshiba_acpi_dev *dev = PDE(file->f_path.dentry->d_inode)->data;
540 541
	char cmd[42];
	size_t len;
L
Linus Torvalds 已提交
542
	int value;
543
	int ret;
L
Linus Torvalds 已提交
544

545 546 547 548 549 550
	len = min(count, sizeof(cmd) - 1);
	if (copy_from_user(cmd, buf, len))
		return -EFAULT;
	cmd[len] = '\0';

	if (sscanf(cmd, " brightness : %i", &value) == 1 &&
551
	    value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) {
552
		ret = set_lcd(dev, value);
553 554 555
		if (ret == 0)
			ret = count;
	} else {
556
		ret = -EINVAL;
557
	}
558
	return ret;
L
Linus Torvalds 已提交
559 560
}

561 562 563 564 565 566 567 568 569
static const struct file_operations lcd_proc_fops = {
	.owner		= THIS_MODULE,
	.open		= lcd_proc_open,
	.read		= seq_read,
	.llseek		= seq_lseek,
	.release	= single_release,
	.write		= lcd_proc_write,
};

570 571 572 573 574 575 576 577
static int get_video_status(struct toshiba_acpi_dev *dev, u32 *status)
{
	u32 hci_result;

	hci_read1(dev, HCI_VIDEO_OUT, status, &hci_result);
	return hci_result == HCI_SUCCESS ? 0 : -EIO;
}

578
static int video_proc_show(struct seq_file *m, void *v)
L
Linus Torvalds 已提交
579
{
580
	struct toshiba_acpi_dev *dev = m->private;
L
Linus Torvalds 已提交
581
	u32 value;
582
	int ret;
L
Linus Torvalds 已提交
583

584 585
	ret = get_video_status(dev, &value);
	if (!ret) {
L
Linus Torvalds 已提交
586 587
		int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0;
		int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0;
L
Len Brown 已提交
588
		int is_tv = (value & HCI_VIDEO_OUT_TV) ? 1 : 0;
589 590 591
		seq_printf(m, "lcd_out:                 %d\n", is_lcd);
		seq_printf(m, "crt_out:                 %d\n", is_crt);
		seq_printf(m, "tv_out:                  %d\n", is_tv);
L
Linus Torvalds 已提交
592 593
	}

594
	return ret;
L
Linus Torvalds 已提交
595 596
}

597
static int video_proc_open(struct inode *inode, struct file *file)
L
Linus Torvalds 已提交
598
{
599
	return single_open(file, video_proc_show, PDE(inode)->data);
600 601 602 603 604
}

static ssize_t video_proc_write(struct file *file, const char __user *buf,
				size_t count, loff_t *pos)
{
605
	struct toshiba_acpi_dev *dev = PDE(file->f_path.dentry->d_inode)->data;
606
	char *cmd, *buffer;
607
	int ret;
L
Linus Torvalds 已提交
608 609 610 611 612
	int value;
	int remain = count;
	int lcd_out = -1;
	int crt_out = -1;
	int tv_out = -1;
A
Al Viro 已提交
613
	u32 video_out;
L
Linus Torvalds 已提交
614

615 616 617 618 619 620 621 622 623 624 625
	cmd = kmalloc(count + 1, GFP_KERNEL);
	if (!cmd)
		return -ENOMEM;
	if (copy_from_user(cmd, buf, count)) {
		kfree(cmd);
		return -EFAULT;
	}
	cmd[count] = '\0';

	buffer = cmd;

L
Linus Torvalds 已提交
626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
	/* scan expression.  Multiple expressions may be delimited with ;
	 *
	 *  NOTE: to keep scanning simple, invalid fields are ignored
	 */
	while (remain) {
		if (sscanf(buffer, " lcd_out : %i", &value) == 1)
			lcd_out = value & 1;
		else if (sscanf(buffer, " crt_out : %i", &value) == 1)
			crt_out = value & 1;
		else if (sscanf(buffer, " tv_out : %i", &value) == 1)
			tv_out = value & 1;
		/* advance to one character past the next ; */
		do {
			++buffer;
			--remain;
		}
L
Len Brown 已提交
642
		while (remain && *(buffer - 1) != ';');
L
Linus Torvalds 已提交
643 644
	}

645 646
	kfree(cmd);

647 648
	ret = get_video_status(dev, &video_out);
	if (!ret) {
649
		unsigned int new_video_out = video_out;
L
Linus Torvalds 已提交
650 651 652 653 654 655 656 657 658
		if (lcd_out != -1)
			_set_bit(&new_video_out, HCI_VIDEO_OUT_LCD, lcd_out);
		if (crt_out != -1)
			_set_bit(&new_video_out, HCI_VIDEO_OUT_CRT, crt_out);
		if (tv_out != -1)
			_set_bit(&new_video_out, HCI_VIDEO_OUT_TV, tv_out);
		/* To avoid unnecessary video disruption, only write the new
		 * video setting if something changed. */
		if (new_video_out != video_out)
S
Seth Forshee 已提交
659
			ret = write_acpi_int(METHOD_VIDEO_OUT, new_video_out);
L
Linus Torvalds 已提交
660 661
	}

S
Seth Forshee 已提交
662
	return ret ? ret : count;
L
Linus Torvalds 已提交
663 664
}

665 666 667 668 669 670 671 672 673
static const struct file_operations video_proc_fops = {
	.owner		= THIS_MODULE,
	.open		= video_proc_open,
	.read		= seq_read,
	.llseek		= seq_lseek,
	.release	= single_release,
	.write		= video_proc_write,
};

674 675 676 677 678 679 680 681
static int get_fan_status(struct toshiba_acpi_dev *dev, u32 *status)
{
	u32 hci_result;

	hci_read1(dev, HCI_FAN, status, &hci_result);
	return hci_result == HCI_SUCCESS ? 0 : -EIO;
}

682
static int fan_proc_show(struct seq_file *m, void *v)
L
Linus Torvalds 已提交
683
{
684
	struct toshiba_acpi_dev *dev = m->private;
685
	int ret;
L
Linus Torvalds 已提交
686 687
	u32 value;

688 689
	ret = get_fan_status(dev, &value);
	if (!ret) {
690
		seq_printf(m, "running:                 %d\n", (value > 0));
691
		seq_printf(m, "force_on:                %d\n", dev->force_fan);
L
Linus Torvalds 已提交
692 693
	}

694
	return ret;
695 696 697 698
}

static int fan_proc_open(struct inode *inode, struct file *file)
{
699
	return single_open(file, fan_proc_show, PDE(inode)->data);
L
Linus Torvalds 已提交
700 701
}

702 703
static ssize_t fan_proc_write(struct file *file, const char __user *buf,
			      size_t count, loff_t *pos)
L
Linus Torvalds 已提交
704
{
705
	struct toshiba_acpi_dev *dev = PDE(file->f_path.dentry->d_inode)->data;
706 707
	char cmd[42];
	size_t len;
L
Linus Torvalds 已提交
708 709 710
	int value;
	u32 hci_result;

711 712 713 714 715 716
	len = min(count, sizeof(cmd) - 1);
	if (copy_from_user(cmd, buf, len))
		return -EFAULT;
	cmd[len] = '\0';

	if (sscanf(cmd, " force_on : %i", &value) == 1 &&
L
Len Brown 已提交
717
	    value >= 0 && value <= 1) {
718
		hci_write1(dev, HCI_FAN, value, &hci_result);
L
Linus Torvalds 已提交
719
		if (hci_result != HCI_SUCCESS)
S
Seth Forshee 已提交
720
			return -EIO;
L
Linus Torvalds 已提交
721
		else
722
			dev->force_fan = value;
L
Linus Torvalds 已提交
723 724 725 726 727 728 729
	} else {
		return -EINVAL;
	}

	return count;
}

730 731 732 733 734 735 736 737 738 739
static const struct file_operations fan_proc_fops = {
	.owner		= THIS_MODULE,
	.open		= fan_proc_open,
	.read		= seq_read,
	.llseek		= seq_lseek,
	.release	= single_release,
	.write		= fan_proc_write,
};

static int keys_proc_show(struct seq_file *m, void *v)
L
Linus Torvalds 已提交
740
{
741
	struct toshiba_acpi_dev *dev = m->private;
L
Linus Torvalds 已提交
742 743 744
	u32 hci_result;
	u32 value;

745
	if (!dev->key_event_valid && dev->system_event_supported) {
746
		hci_read1(dev, HCI_SYSTEM_EVENT, &value, &hci_result);
L
Linus Torvalds 已提交
747
		if (hci_result == HCI_SUCCESS) {
748 749
			dev->key_event_valid = 1;
			dev->last_key_event = value;
L
Linus Torvalds 已提交
750 751 752 753 754 755
		} else if (hci_result == HCI_EMPTY) {
			/* better luck next time */
		} else if (hci_result == HCI_NOT_SUPPORTED) {
			/* This is a workaround for an unresolved issue on
			 * some machines where system events sporadically
			 * become disabled. */
756
			hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result);
757
			pr_notice("Re-enabled hotkeys\n");
L
Linus Torvalds 已提交
758
		} else {
759
			pr_err("Error reading hotkey status\n");
S
Seth Forshee 已提交
760
			return -EIO;
L
Linus Torvalds 已提交
761 762 763
		}
	}

764 765
	seq_printf(m, "hotkey_ready:            %d\n", dev->key_event_valid);
	seq_printf(m, "hotkey:                  0x%04x\n", dev->last_key_event);
766 767
	return 0;
}
L
Linus Torvalds 已提交
768

769 770
static int keys_proc_open(struct inode *inode, struct file *file)
{
771
	return single_open(file, keys_proc_show, PDE(inode)->data);
L
Linus Torvalds 已提交
772 773
}

774 775
static ssize_t keys_proc_write(struct file *file, const char __user *buf,
			       size_t count, loff_t *pos)
L
Linus Torvalds 已提交
776
{
777
	struct toshiba_acpi_dev *dev = PDE(file->f_path.dentry->d_inode)->data;
778 779
	char cmd[42];
	size_t len;
L
Linus Torvalds 已提交
780 781
	int value;

782 783 784 785 786 787
	len = min(count, sizeof(cmd) - 1);
	if (copy_from_user(cmd, buf, len))
		return -EFAULT;
	cmd[len] = '\0';

	if (sscanf(cmd, " hotkey_ready : %i", &value) == 1 && value == 0) {
788
		dev->key_event_valid = 0;
L
Linus Torvalds 已提交
789 790 791 792 793 794 795
	} else {
		return -EINVAL;
	}

	return count;
}

796 797 798 799 800 801 802 803 804 805
static const struct file_operations keys_proc_fops = {
	.owner		= THIS_MODULE,
	.open		= keys_proc_open,
	.read		= seq_read,
	.llseek		= seq_lseek,
	.release	= single_release,
	.write		= keys_proc_write,
};

static int version_proc_show(struct seq_file *m, void *v)
L
Linus Torvalds 已提交
806
{
807 808 809
	seq_printf(m, "driver:                  %s\n", TOSHIBA_ACPI_VERSION);
	seq_printf(m, "proc_interface:          %d\n", PROC_INTERFACE_VERSION);
	return 0;
L
Linus Torvalds 已提交
810 811
}

812 813 814 815 816 817 818 819 820 821 822 823 824
static int version_proc_open(struct inode *inode, struct file *file)
{
	return single_open(file, version_proc_show, PDE(inode)->data);
}

static const struct file_operations version_proc_fops = {
	.owner		= THIS_MODULE,
	.open		= version_proc_open,
	.read		= seq_read,
	.llseek		= seq_lseek,
	.release	= single_release,
};

L
Linus Torvalds 已提交
825 826 827 828 829
/* proc and module init
 */

#define PROC_TOSHIBA		"toshiba"

830 831
static void __devinit
create_toshiba_proc_entries(struct toshiba_acpi_dev *dev)
L
Linus Torvalds 已提交
832
{
833 834 835 836 837 838 839 840 841 842 843 844
	if (dev->backlight_dev)
		proc_create_data("lcd", S_IRUGO | S_IWUSR, toshiba_proc_dir,
				 &lcd_proc_fops, dev);
	if (dev->video_supported)
		proc_create_data("video", S_IRUGO | S_IWUSR, toshiba_proc_dir,
				 &video_proc_fops, dev);
	if (dev->fan_supported)
		proc_create_data("fan", S_IRUGO | S_IWUSR, toshiba_proc_dir,
				 &fan_proc_fops, dev);
	if (dev->hotkey_dev)
		proc_create_data("keys", S_IRUGO | S_IWUSR, toshiba_proc_dir,
				 &keys_proc_fops, dev);
845 846
	proc_create_data("version", S_IRUGO, toshiba_proc_dir,
			 &version_proc_fops, dev);
L
Linus Torvalds 已提交
847 848
}

849
static void remove_toshiba_proc_entries(struct toshiba_acpi_dev *dev)
L
Linus Torvalds 已提交
850
{
851 852 853 854 855 856 857 858
	if (dev->backlight_dev)
		remove_proc_entry("lcd", toshiba_proc_dir);
	if (dev->video_supported)
		remove_proc_entry("video", toshiba_proc_dir);
	if (dev->fan_supported)
		remove_proc_entry("fan", toshiba_proc_dir);
	if (dev->hotkey_dev)
		remove_proc_entry("keys", toshiba_proc_dir);
859
	remove_proc_entry("version", toshiba_proc_dir);
L
Linus Torvalds 已提交
860 861
}

L
Lionel Debroux 已提交
862
static const struct backlight_ops toshiba_backlight_data = {
863 864 865 866
        .get_brightness = get_lcd,
        .update_status  = set_lcd_status,
};

867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932
static bool toshiba_acpi_i8042_filter(unsigned char data, unsigned char str,
				      struct serio *port)
{
	if (str & 0x20)
		return false;

	if (unlikely(data == 0xe0))
		return false;

	if ((data & 0x7f) == TOS1900_FN_SCAN) {
		schedule_work(&toshiba_acpi->hotkey_work);
		return true;
	}

	return false;
}

static void toshiba_acpi_hotkey_work(struct work_struct *work)
{
	acpi_handle ec_handle = ec_get_handle();
	acpi_status status;

	if (!ec_handle)
		return;

	status = acpi_evaluate_object(ec_handle, "NTFY", NULL, NULL);
	if (ACPI_FAILURE(status))
		pr_err("ACPI NTFY method execution failed\n");
}

/*
 * Returns hotkey scancode, or < 0 on failure.
 */
static int toshiba_acpi_query_hotkey(struct toshiba_acpi_dev *dev)
{
	struct acpi_buffer buf;
	union acpi_object out_obj;
	acpi_status status;

	buf.pointer = &out_obj;
	buf.length = sizeof(out_obj);

	status = acpi_evaluate_object(dev->acpi_dev->handle, "INFO",
				      NULL, &buf);
	if (ACPI_FAILURE(status) || out_obj.type != ACPI_TYPE_INTEGER) {
		pr_err("ACPI INFO method execution failed\n");
		return -EIO;
	}

	return out_obj.integer.value;
}

static void toshiba_acpi_report_hotkey(struct toshiba_acpi_dev *dev,
				       int scancode)
{
	if (scancode == 0x100)
		return;

	/* act on key press; ignore key release */
	if (scancode & 0x80)
		return;

	if (!sparse_keymap_report_event(dev->hotkey_dev, scancode, 1, true))
		pr_info("Unknown key %x\n", scancode);
}

933
static int __devinit toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
934 935
{
	acpi_status status;
936
	acpi_handle ec_handle, handle;
937
	int error;
938
	u32 hci_result;
939

940 941
	dev->hotkey_dev = input_allocate_device();
	if (!dev->hotkey_dev) {
942
		pr_info("Unable to register input device\n");
943 944 945
		return -ENOMEM;
	}

946
	dev->hotkey_dev->name = "Toshiba input device";
947
	dev->hotkey_dev->phys = "toshiba_acpi/input0";
948
	dev->hotkey_dev->id.bustype = BUS_HOST;
949

950
	error = sparse_keymap_setup(dev->hotkey_dev, toshiba_acpi_keymap, NULL);
951 952 953
	if (error)
		goto err_free_dev;

954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995
	/*
	 * For some machines the SCI responsible for providing hotkey
	 * notification doesn't fire. We can trigger the notification
	 * whenever the Fn key is pressed using the NTFY method, if
	 * supported, so if it's present set up an i8042 key filter
	 * for this purpose.
	 */
	status = AE_ERROR;
	ec_handle = ec_get_handle();
	if (ec_handle)
		status = acpi_get_handle(ec_handle, "NTFY", &handle);

	if (ACPI_SUCCESS(status)) {
		INIT_WORK(&dev->hotkey_work, toshiba_acpi_hotkey_work);

		error = i8042_install_filter(toshiba_acpi_i8042_filter);
		if (error) {
			pr_err("Error installing key filter\n");
			goto err_free_keymap;
		}

		dev->ntfy_supported = 1;
	}

	/*
	 * Determine hotkey query interface. Prefer using the INFO
	 * method when it is available.
	 */
	status = acpi_get_handle(dev->acpi_dev->handle, "INFO", &handle);
	if (ACPI_SUCCESS(status)) {
		dev->info_supported = 1;
	} else {
		hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result);
		if (hci_result == HCI_SUCCESS)
			dev->system_event_supported = 1;
	}

	if (!dev->info_supported && !dev->system_event_supported) {
		pr_warn("No hotkey query interface found\n");
		goto err_remove_filter;
	}

996
	status = acpi_evaluate_object(dev->acpi_dev->handle, "ENAB", NULL, NULL);
997
	if (ACPI_FAILURE(status)) {
998
		pr_info("Unable to enable hotkeys\n");
999
		error = -ENODEV;
1000
		goto err_remove_filter;
1001 1002
	}

1003
	error = input_register_device(dev->hotkey_dev);
1004
	if (error) {
1005
		pr_info("Unable to register input device\n");
1006
		goto err_remove_filter;
1007 1008
	}

1009
	hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_ENABLE, &hci_result);
1010
	return 0;
1011

1012 1013 1014
 err_remove_filter:
	if (dev->ntfy_supported)
		i8042_remove_filter(toshiba_acpi_i8042_filter);
1015
 err_free_keymap:
1016
	sparse_keymap_free(dev->hotkey_dev);
1017
 err_free_dev:
1018 1019
	input_free_device(dev->hotkey_dev);
	dev->hotkey_dev = NULL;
1020
	return error;
1021 1022
}

1023
static int toshiba_acpi_remove(struct acpi_device *acpi_dev, int type)
1024
{
1025
	struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
1026

1027
	remove_toshiba_proc_entries(dev);
1028

1029 1030 1031 1032 1033
	if (dev->ntfy_supported) {
		i8042_remove_filter(toshiba_acpi_i8042_filter);
		cancel_work_sync(&dev->hotkey_work);
	}

1034 1035 1036 1037
	if (dev->hotkey_dev) {
		input_unregister_device(dev->hotkey_dev);
		sparse_keymap_free(dev->hotkey_dev);
	}
1038

1039 1040 1041 1042
	if (dev->bt_rfk) {
		rfkill_unregister(dev->bt_rfk);
		rfkill_destroy(dev->bt_rfk);
	}
1043

1044 1045
	if (dev->backlight_dev)
		backlight_device_unregister(dev->backlight_dev);
1046

1047
	if (dev->illumination_supported)
1048
		led_classdev_unregister(&dev->led_dev);
1049

1050 1051 1052
	if (toshiba_acpi)
		toshiba_acpi = NULL;

1053
	kfree(dev);
1054

1055
	return 0;
1056 1057
}

1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073
static const char * __devinit find_hci_method(acpi_handle handle)
{
	acpi_status status;
	acpi_handle hci_handle;

	status = acpi_get_handle(handle, "GHCI", &hci_handle);
	if (ACPI_SUCCESS(status))
		return "GHCI";

	status = acpi_get_handle(handle, "SPFC", &hci_handle);
	if (ACPI_SUCCESS(status))
		return "SPFC";

	return NULL;
}

1074
static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev)
L
Linus Torvalds 已提交
1075
{
1076
	struct toshiba_acpi_dev *dev;
1077
	const char *hci_method;
1078
	u32 dummy;
1079 1080
	bool bt_present;
	int ret = 0;
1081
	struct backlight_properties props;
L
Linus Torvalds 已提交
1082

1083 1084 1085
	if (toshiba_acpi)
		return -EBUSY;

1086 1087 1088
	pr_info("Toshiba Laptop ACPI Extras version %s\n",
	       TOSHIBA_ACPI_VERSION);

1089 1090 1091
	hci_method = find_hci_method(acpi_dev->handle);
	if (!hci_method) {
		pr_err("HCI interface not found\n");
1092
		return -ENODEV;
1093
	}
1094

1095 1096 1097 1098
	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
	if (!dev)
		return -ENOMEM;
	dev->acpi_dev = acpi_dev;
1099
	dev->method_hci = hci_method;
1100
	acpi_dev->driver_data = dev;
L
Luming Yu 已提交
1101

1102 1103
	if (toshiba_acpi_setup_keyboard(dev))
		pr_info("Unable to activate hotkeys\n");
1104 1105

	mutex_init(&dev->mutex);
L
Linus Torvalds 已提交
1106

1107
	memset(&props, 0, sizeof(props));
M
Matthew Garrett 已提交
1108
	props.type = BACKLIGHT_PLATFORM;
1109
	props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
1110 1111 1112 1113 1114 1115 1116
	dev->backlight_dev = backlight_device_register("toshiba",
						       &acpi_dev->dev,
						       dev,
						       &toshiba_backlight_data,
						       &props);
	if (IS_ERR(dev->backlight_dev)) {
		ret = PTR_ERR(dev->backlight_dev);
1117

1118
		pr_err("Could not register toshiba backlight device\n");
1119 1120
		dev->backlight_dev = NULL;
		goto error;
1121
	}
1122
	dev->backlight_dev->props.brightness = get_lcd(dev->backlight_dev);
L
Linus Torvalds 已提交
1123

1124
	/* Register rfkill switch for Bluetooth */
1125 1126 1127 1128 1129 1130 1131
	if (hci_get_bt_present(dev, &bt_present) == HCI_SUCCESS && bt_present) {
		dev->bt_rfk = rfkill_alloc("Toshiba Bluetooth",
					   &acpi_dev->dev,
					   RFKILL_TYPE_BLUETOOTH,
					   &toshiba_rfk_ops,
					   dev);
		if (!dev->bt_rfk) {
1132
			pr_err("unable to allocate rfkill device\n");
1133 1134
			ret = -ENOMEM;
			goto error;
1135 1136
		}

1137
		ret = rfkill_register(dev->bt_rfk);
1138
		if (ret) {
1139
			pr_err("unable to register rfkill device\n");
1140 1141
			rfkill_destroy(dev->bt_rfk);
			goto error;
1142
		}
1143 1144
	}

1145 1146 1147 1148 1149 1150
	if (toshiba_illumination_available(dev)) {
		dev->led_dev.name = "toshiba::illumination";
		dev->led_dev.max_brightness = 1;
		dev->led_dev.brightness_set = toshiba_illumination_set;
		dev->led_dev.brightness_get = toshiba_illumination_get;
		if (!led_classdev_register(&acpi_dev->dev, &dev->led_dev))
1151
			dev->illumination_supported = 1;
1152 1153
	}

1154 1155 1156 1157 1158 1159 1160 1161 1162 1163
	/* Determine whether or not BIOS supports fan and video interfaces */

	ret = get_video_status(dev, &dummy);
	dev->video_supported = !ret;

	ret = get_fan_status(dev, &dummy);
	dev->fan_supported = !ret;

	create_toshiba_proc_entries(dev);

1164 1165
	toshiba_acpi = dev;

1166
	return 0;
1167 1168 1169 1170 1171 1172 1173 1174 1175 1176

error:
	toshiba_acpi_remove(acpi_dev, 0);
	return ret;
}

static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event)
{
	struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
	u32 hci_result, value;
1177
	int retries = 3;
1178
	int scancode;
1179

1180
	if (event != 0x80)
1181
		return;
1182

1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208
	if (dev->info_supported) {
		scancode = toshiba_acpi_query_hotkey(dev);
		if (scancode < 0)
			pr_err("Failed to query hotkey event\n");
		else if (scancode != 0)
			toshiba_acpi_report_hotkey(dev, scancode);
	} else if (dev->system_event_supported) {
		do {
			hci_read1(dev, HCI_SYSTEM_EVENT, &value, &hci_result);
			switch (hci_result) {
			case HCI_SUCCESS:
				toshiba_acpi_report_hotkey(dev, (int)value);
				break;
			case HCI_NOT_SUPPORTED:
				/*
				 * This is a workaround for an unresolved
				 * issue on some machines where system events
				 * sporadically become disabled.
				 */
				hci_write1(dev, HCI_SYSTEM_EVENT, 1,
					   &hci_result);
				pr_notice("Re-enabled hotkeys\n");
				/* fall through */
			default:
				retries--;
				break;
1209
			}
1210 1211
		} while (retries && hci_result != HCI_EMPTY);
	}
1212 1213
}

1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235
static int toshiba_acpi_suspend(struct acpi_device *acpi_dev,
				pm_message_t state)
{
	struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
	u32 result;

	if (dev->hotkey_dev)
		hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_DISABLE, &result);

	return 0;
}

static int toshiba_acpi_resume(struct acpi_device *acpi_dev)
{
	struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
	u32 result;

	if (dev->hotkey_dev)
		hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_ENABLE, &result);

	return 0;
}
1236 1237 1238 1239 1240 1241 1242 1243 1244 1245

static struct acpi_driver toshiba_acpi_driver = {
	.name	= "Toshiba ACPI driver",
	.owner	= THIS_MODULE,
	.ids	= toshiba_device_ids,
	.flags	= ACPI_DRIVER_ALL_NOTIFY_EVENTS,
	.ops	= {
		.add		= toshiba_acpi_add,
		.remove		= toshiba_acpi_remove,
		.notify		= toshiba_acpi_notify,
1246 1247
		.suspend	= toshiba_acpi_suspend,
		.resume		= toshiba_acpi_resume,
1248 1249 1250 1251 1252 1253 1254
	},
};

static int __init toshiba_acpi_init(void)
{
	int ret;

1255 1256 1257 1258 1259 1260 1261 1262
	/*
	 * Machines with this WMI guid aren't supported due to bugs in
	 * their AML. This check relies on wmi initializing before
	 * toshiba_acpi to guarantee guids have been identified.
	 */
	if (wmi_has_guid(TOSHIBA_WMI_EVENT_GUID))
		return -ENODEV;

1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282
	toshiba_proc_dir = proc_mkdir(PROC_TOSHIBA, acpi_root_dir);
	if (!toshiba_proc_dir) {
		pr_err("Unable to create proc dir " PROC_TOSHIBA "\n");
		return -ENODEV;
	}

	ret = acpi_bus_register_driver(&toshiba_acpi_driver);
	if (ret) {
		pr_err("Failed to register ACPI driver: %d\n", ret);
		remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
	}

	return ret;
}

static void __exit toshiba_acpi_exit(void)
{
	acpi_bus_unregister_driver(&toshiba_acpi_driver);
	if (toshiba_proc_dir)
		remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
L
Linus Torvalds 已提交
1283 1284 1285 1286
}

module_init(toshiba_acpi_init);
module_exit(toshiba_acpi_exit);