• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/platform/x86/
1/*
2 *  toshiba_acpi.c - Toshiba Laptop ACPI Extras
3 *
4 *
5 *  Copyright (C) 2002-2004 John Belmonte
6 *  Copyright (C) 2008 Philip Langdale
7 *  Copyright (C) 2010 Pierre Ducroquet
8 *
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 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this program; if not, write to the Free Software
21 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 *
23 *
24 *  The devolpment page for this driver is located at
25 *  http://memebeam.org/toys/ToshibaAcpiDriver.
26 *
27 *  Credits:
28 *	Jonathan A. Buzzard - Toshiba HCI info, and critical tips on reverse
29 *		engineering the Windows drivers
30 *	Yasushi Nagato - changes for linux kernel 2.4 -> 2.5
31 *	Rob Miller - TV out and hotkeys help
32 *
33 *
34 *  TODO
35 *
36 */
37
38#define TOSHIBA_ACPI_VERSION	"0.19"
39#define PROC_INTERFACE_VERSION	1
40
41#include <linux/kernel.h>
42#include <linux/module.h>
43#include <linux/init.h>
44#include <linux/types.h>
45#include <linux/proc_fs.h>
46#include <linux/seq_file.h>
47#include <linux/backlight.h>
48#include <linux/platform_device.h>
49#include <linux/rfkill.h>
50#include <linux/input.h>
51#include <linux/leds.h>
52#include <linux/slab.h>
53
54#include <asm/uaccess.h>
55
56#include <acpi/acpi_drivers.h>
57
58MODULE_AUTHOR("John Belmonte");
59MODULE_DESCRIPTION("Toshiba Laptop ACPI Extras Driver");
60MODULE_LICENSE("GPL");
61
62#define MY_LOGPREFIX "toshiba_acpi: "
63#define MY_ERR KERN_ERR MY_LOGPREFIX
64#define MY_NOTICE KERN_NOTICE MY_LOGPREFIX
65#define MY_INFO KERN_INFO MY_LOGPREFIX
66
67/* Toshiba ACPI method paths */
68#define METHOD_LCD_BRIGHTNESS	"\\_SB_.PCI0.VGA_.LCD_._BCM"
69#define TOSH_INTERFACE_1	"\\_SB_.VALD"
70#define TOSH_INTERFACE_2	"\\_SB_.VALZ"
71#define METHOD_VIDEO_OUT	"\\_SB_.VALX.DSSX"
72#define GHCI_METHOD		".GHCI"
73
74/* Toshiba HCI interface definitions
75 *
76 * HCI is Toshiba's "Hardware Control Interface" which is supposed to
77 * be uniform across all their models.  Ideally we would just call
78 * dedicated ACPI methods instead of using this primitive interface.
79 * However the ACPI methods seem to be incomplete in some areas (for
80 * example they allow setting, but not reading, the LCD brightness value),
81 * so this is still useful.
82 */
83
84#define HCI_WORDS			6
85
86/* operations */
87#define HCI_SET				0xff00
88#define HCI_GET				0xfe00
89
90/* return codes */
91#define HCI_SUCCESS			0x0000
92#define HCI_FAILURE			0x1000
93#define HCI_NOT_SUPPORTED		0x8000
94#define HCI_EMPTY			0x8c00
95
96/* registers */
97#define HCI_FAN				0x0004
98#define HCI_SYSTEM_EVENT		0x0016
99#define HCI_VIDEO_OUT			0x001c
100#define HCI_HOTKEY_EVENT		0x001e
101#define HCI_LCD_BRIGHTNESS		0x002a
102#define HCI_WIRELESS			0x0056
103
104/* field definitions */
105#define HCI_LCD_BRIGHTNESS_BITS		3
106#define HCI_LCD_BRIGHTNESS_SHIFT	(16-HCI_LCD_BRIGHTNESS_BITS)
107#define HCI_LCD_BRIGHTNESS_LEVELS	(1 << HCI_LCD_BRIGHTNESS_BITS)
108#define HCI_VIDEO_OUT_LCD		0x1
109#define HCI_VIDEO_OUT_CRT		0x2
110#define HCI_VIDEO_OUT_TV		0x4
111#define HCI_WIRELESS_KILL_SWITCH	0x01
112#define HCI_WIRELESS_BT_PRESENT		0x0f
113#define HCI_WIRELESS_BT_ATTACH		0x40
114#define HCI_WIRELESS_BT_POWER		0x80
115
116static const struct acpi_device_id toshiba_device_ids[] = {
117	{"TOS6200", 0},
118	{"TOS6208", 0},
119	{"TOS1900", 0},
120	{"", 0},
121};
122MODULE_DEVICE_TABLE(acpi, toshiba_device_ids);
123
124struct key_entry {
125	char type;
126	u16 code;
127	u16 keycode;
128};
129
130enum {KE_KEY, KE_END};
131
132static struct key_entry toshiba_acpi_keymap[]  = {
133	{KE_KEY, 0x101, KEY_MUTE},
134	{KE_KEY, 0x102, KEY_ZOOMOUT},
135	{KE_KEY, 0x103, KEY_ZOOMIN},
136	{KE_KEY, 0x13b, KEY_COFFEE},
137	{KE_KEY, 0x13c, KEY_BATTERY},
138	{KE_KEY, 0x13d, KEY_SLEEP},
139	{KE_KEY, 0x13e, KEY_SUSPEND},
140	{KE_KEY, 0x13f, KEY_SWITCHVIDEOMODE},
141	{KE_KEY, 0x140, KEY_BRIGHTNESSDOWN},
142	{KE_KEY, 0x141, KEY_BRIGHTNESSUP},
143	{KE_KEY, 0x142, KEY_WLAN},
144	{KE_KEY, 0x143, KEY_PROG1},
145	{KE_KEY, 0xb05, KEY_PROG2},
146	{KE_KEY, 0xb06, KEY_WWW},
147	{KE_KEY, 0xb07, KEY_MAIL},
148	{KE_KEY, 0xb30, KEY_STOP},
149	{KE_KEY, 0xb31, KEY_PREVIOUSSONG},
150	{KE_KEY, 0xb32, KEY_NEXTSONG},
151	{KE_KEY, 0xb33, KEY_PLAYPAUSE},
152	{KE_KEY, 0xb5a, KEY_MEDIA},
153	{KE_END, 0, 0},
154};
155
156/* utility
157 */
158
159static __inline__ void _set_bit(u32 * word, u32 mask, int value)
160{
161	*word = (*word & ~mask) | (mask * value);
162}
163
164/* acpi interface wrappers
165 */
166
167static int is_valid_acpi_path(const char *methodName)
168{
169	acpi_handle handle;
170	acpi_status status;
171
172	status = acpi_get_handle(NULL, (char *)methodName, &handle);
173	return !ACPI_FAILURE(status);
174}
175
176static int write_acpi_int(const char *methodName, int val)
177{
178	struct acpi_object_list params;
179	union acpi_object in_objs[1];
180	acpi_status status;
181
182	params.count = ARRAY_SIZE(in_objs);
183	params.pointer = in_objs;
184	in_objs[0].type = ACPI_TYPE_INTEGER;
185	in_objs[0].integer.value = val;
186
187	status = acpi_evaluate_object(NULL, (char *)methodName, &params, NULL);
188	return (status == AE_OK);
189}
190
191
192static const char *method_hci /*= 0*/ ;
193
194/* Perform a raw HCI call.  Here we don't care about input or output buffer
195 * format.
196 */
197static acpi_status hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
198{
199	struct acpi_object_list params;
200	union acpi_object in_objs[HCI_WORDS];
201	struct acpi_buffer results;
202	union acpi_object out_objs[HCI_WORDS + 1];
203	acpi_status status;
204	int i;
205
206	params.count = HCI_WORDS;
207	params.pointer = in_objs;
208	for (i = 0; i < HCI_WORDS; ++i) {
209		in_objs[i].type = ACPI_TYPE_INTEGER;
210		in_objs[i].integer.value = in[i];
211	}
212
213	results.length = sizeof(out_objs);
214	results.pointer = out_objs;
215
216	status = acpi_evaluate_object(NULL, (char *)method_hci, &params,
217				      &results);
218	if ((status == AE_OK) && (out_objs->package.count <= HCI_WORDS)) {
219		for (i = 0; i < out_objs->package.count; ++i) {
220			out[i] = out_objs->package.elements[i].integer.value;
221		}
222	}
223
224	return status;
225}
226
227/* common hci tasks (get or set one or two value)
228 *
229 * In addition to the ACPI status, the HCI system returns a result which
230 * may be useful (such as "not supported").
231 */
232
233static acpi_status hci_write1(u32 reg, u32 in1, u32 * result)
234{
235	u32 in[HCI_WORDS] = { HCI_SET, reg, in1, 0, 0, 0 };
236	u32 out[HCI_WORDS];
237	acpi_status status = hci_raw(in, out);
238	*result = (status == AE_OK) ? out[0] : HCI_FAILURE;
239	return status;
240}
241
242static acpi_status hci_read1(u32 reg, u32 * out1, u32 * result)
243{
244	u32 in[HCI_WORDS] = { HCI_GET, reg, 0, 0, 0, 0 };
245	u32 out[HCI_WORDS];
246	acpi_status status = hci_raw(in, out);
247	*out1 = out[2];
248	*result = (status == AE_OK) ? out[0] : HCI_FAILURE;
249	return status;
250}
251
252static acpi_status hci_write2(u32 reg, u32 in1, u32 in2, u32 *result)
253{
254	u32 in[HCI_WORDS] = { HCI_SET, reg, in1, in2, 0, 0 };
255	u32 out[HCI_WORDS];
256	acpi_status status = hci_raw(in, out);
257	*result = (status == AE_OK) ? out[0] : HCI_FAILURE;
258	return status;
259}
260
261static acpi_status hci_read2(u32 reg, u32 *out1, u32 *out2, u32 *result)
262{
263	u32 in[HCI_WORDS] = { HCI_GET, reg, *out1, *out2, 0, 0 };
264	u32 out[HCI_WORDS];
265	acpi_status status = hci_raw(in, out);
266	*out1 = out[2];
267	*out2 = out[3];
268	*result = (status == AE_OK) ? out[0] : HCI_FAILURE;
269	return status;
270}
271
272struct toshiba_acpi_dev {
273	struct platform_device *p_dev;
274	struct rfkill *bt_rfk;
275	struct input_dev *hotkey_dev;
276	int illumination_installed;
277	acpi_handle handle;
278
279	const char *bt_name;
280
281	struct mutex mutex;
282};
283
284/* Illumination support */
285static int toshiba_illumination_available(void)
286{
287	u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
288	u32 out[HCI_WORDS];
289	acpi_status status;
290
291	in[0] = 0xf100;
292	status = hci_raw(in, out);
293	if (ACPI_FAILURE(status)) {
294		printk(MY_INFO "Illumination device not available\n");
295		return 0;
296	}
297	in[0] = 0xf400;
298	status = hci_raw(in, out);
299	return 1;
300}
301
302static void toshiba_illumination_set(struct led_classdev *cdev,
303				     enum led_brightness brightness)
304{
305	u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
306	u32 out[HCI_WORDS];
307	acpi_status status;
308
309	/* First request : initialize communication. */
310	in[0] = 0xf100;
311	status = hci_raw(in, out);
312	if (ACPI_FAILURE(status)) {
313		printk(MY_INFO "Illumination device not available\n");
314		return;
315	}
316
317	if (brightness) {
318		/* Switch the illumination on */
319		in[0] = 0xf400;
320		in[1] = 0x14e;
321		in[2] = 1;
322		status = hci_raw(in, out);
323		if (ACPI_FAILURE(status)) {
324			printk(MY_INFO "ACPI call for illumination failed.\n");
325			return;
326		}
327	} else {
328		/* Switch the illumination off */
329		in[0] = 0xf400;
330		in[1] = 0x14e;
331		in[2] = 0;
332		status = hci_raw(in, out);
333		if (ACPI_FAILURE(status)) {
334			printk(MY_INFO "ACPI call for illumination failed.\n");
335			return;
336		}
337	}
338
339	/* Last request : close communication. */
340	in[0] = 0xf200;
341	in[1] = 0;
342	in[2] = 0;
343	hci_raw(in, out);
344}
345
346static enum led_brightness toshiba_illumination_get(struct led_classdev *cdev)
347{
348	u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 };
349	u32 out[HCI_WORDS];
350	acpi_status status;
351	enum led_brightness result;
352
353	/*��First request : initialize communication. */
354	in[0] = 0xf100;
355	status = hci_raw(in, out);
356	if (ACPI_FAILURE(status)) {
357		printk(MY_INFO "Illumination device not available\n");
358		return LED_OFF;
359	}
360
361	/* Check the illumination */
362	in[0] = 0xf300;
363	in[1] = 0x14e;
364	status = hci_raw(in, out);
365	if (ACPI_FAILURE(status)) {
366		printk(MY_INFO "ACPI call for illumination failed.\n");
367		return LED_OFF;
368	}
369
370	result = out[2] ? LED_FULL : LED_OFF;
371
372	/* Last request : close communication. */
373	in[0] = 0xf200;
374	in[1] = 0;
375	in[2] = 0;
376	hci_raw(in, out);
377
378	return result;
379}
380
381static struct led_classdev toshiba_led = {
382	.name           = "toshiba::illumination",
383	.max_brightness = 1,
384	.brightness_set = toshiba_illumination_set,
385	.brightness_get = toshiba_illumination_get,
386};
387
388static struct toshiba_acpi_dev toshiba_acpi = {
389	.bt_name = "Toshiba Bluetooth",
390};
391
392/* Bluetooth rfkill handlers */
393
394static u32 hci_get_bt_present(bool *present)
395{
396	u32 hci_result;
397	u32 value, value2;
398
399	value = 0;
400	value2 = 0;
401	hci_read2(HCI_WIRELESS, &value, &value2, &hci_result);
402	if (hci_result == HCI_SUCCESS)
403		*present = (value & HCI_WIRELESS_BT_PRESENT) ? true : false;
404
405	return hci_result;
406}
407
408static u32 hci_get_radio_state(bool *radio_state)
409{
410	u32 hci_result;
411	u32 value, value2;
412
413	value = 0;
414	value2 = 0x0001;
415	hci_read2(HCI_WIRELESS, &value, &value2, &hci_result);
416
417	*radio_state = value & HCI_WIRELESS_KILL_SWITCH;
418	return hci_result;
419}
420
421static int bt_rfkill_set_block(void *data, bool blocked)
422{
423	struct toshiba_acpi_dev *dev = data;
424	u32 result1, result2;
425	u32 value;
426	int err;
427	bool radio_state;
428
429	value = (blocked == false);
430
431	mutex_lock(&dev->mutex);
432	if (hci_get_radio_state(&radio_state) != HCI_SUCCESS) {
433		err = -EBUSY;
434		goto out;
435	}
436
437	if (!radio_state) {
438		err = 0;
439		goto out;
440	}
441
442	hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_POWER, &result1);
443	hci_write2(HCI_WIRELESS, value, HCI_WIRELESS_BT_ATTACH, &result2);
444
445	if (result1 != HCI_SUCCESS || result2 != HCI_SUCCESS)
446		err = -EBUSY;
447	else
448		err = 0;
449 out:
450	mutex_unlock(&dev->mutex);
451	return err;
452}
453
454static void bt_rfkill_poll(struct rfkill *rfkill, void *data)
455{
456	bool new_rfk_state;
457	bool value;
458	u32 hci_result;
459	struct toshiba_acpi_dev *dev = data;
460
461	mutex_lock(&dev->mutex);
462
463	hci_result = hci_get_radio_state(&value);
464	if (hci_result != HCI_SUCCESS) {
465		/* Can't do anything useful */
466		mutex_unlock(&dev->mutex);
467		return;
468	}
469
470	new_rfk_state = value;
471
472	mutex_unlock(&dev->mutex);
473
474	if (rfkill_set_hw_state(rfkill, !new_rfk_state))
475		bt_rfkill_set_block(data, true);
476}
477
478static const struct rfkill_ops toshiba_rfk_ops = {
479	.set_block = bt_rfkill_set_block,
480	.poll = bt_rfkill_poll,
481};
482
483static struct proc_dir_entry *toshiba_proc_dir /*= 0*/ ;
484static struct backlight_device *toshiba_backlight_device;
485static int force_fan;
486static int last_key_event;
487static int key_event_valid;
488
489static int get_lcd(struct backlight_device *bd)
490{
491	u32 hci_result;
492	u32 value;
493
494	hci_read1(HCI_LCD_BRIGHTNESS, &value, &hci_result);
495	if (hci_result == HCI_SUCCESS) {
496		return (value >> HCI_LCD_BRIGHTNESS_SHIFT);
497	} else
498		return -EFAULT;
499}
500
501static int lcd_proc_show(struct seq_file *m, void *v)
502{
503	int value = get_lcd(NULL);
504
505	if (value >= 0) {
506		seq_printf(m, "brightness:              %d\n", value);
507		seq_printf(m, "brightness_levels:       %d\n",
508			     HCI_LCD_BRIGHTNESS_LEVELS);
509	} else {
510		printk(MY_ERR "Error reading LCD brightness\n");
511	}
512
513	return 0;
514}
515
516static int lcd_proc_open(struct inode *inode, struct file *file)
517{
518	return single_open(file, lcd_proc_show, NULL);
519}
520
521static int set_lcd(int value)
522{
523	u32 hci_result;
524
525	value = value << HCI_LCD_BRIGHTNESS_SHIFT;
526	hci_write1(HCI_LCD_BRIGHTNESS, value, &hci_result);
527	if (hci_result != HCI_SUCCESS)
528		return -EFAULT;
529
530	return 0;
531}
532
533static int set_lcd_status(struct backlight_device *bd)
534{
535	return set_lcd(bd->props.brightness);
536}
537
538static ssize_t lcd_proc_write(struct file *file, const char __user *buf,
539			      size_t count, loff_t *pos)
540{
541	char cmd[42];
542	size_t len;
543	int value;
544	int ret;
545
546	len = min(count, sizeof(cmd) - 1);
547	if (copy_from_user(cmd, buf, len))
548		return -EFAULT;
549	cmd[len] = '\0';
550
551	if (sscanf(cmd, " brightness : %i", &value) == 1 &&
552	    value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) {
553		ret = set_lcd(value);
554		if (ret == 0)
555			ret = count;
556	} else {
557		ret = -EINVAL;
558	}
559	return ret;
560}
561
562static const struct file_operations lcd_proc_fops = {
563	.owner		= THIS_MODULE,
564	.open		= lcd_proc_open,
565	.read		= seq_read,
566	.llseek		= seq_lseek,
567	.release	= single_release,
568	.write		= lcd_proc_write,
569};
570
571static int video_proc_show(struct seq_file *m, void *v)
572{
573	u32 hci_result;
574	u32 value;
575
576	hci_read1(HCI_VIDEO_OUT, &value, &hci_result);
577	if (hci_result == HCI_SUCCESS) {
578		int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0;
579		int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0;
580		int is_tv = (value & HCI_VIDEO_OUT_TV) ? 1 : 0;
581		seq_printf(m, "lcd_out:                 %d\n", is_lcd);
582		seq_printf(m, "crt_out:                 %d\n", is_crt);
583		seq_printf(m, "tv_out:                  %d\n", is_tv);
584	} else {
585		printk(MY_ERR "Error reading video out status\n");
586	}
587
588	return 0;
589}
590
591static int video_proc_open(struct inode *inode, struct file *file)
592{
593	return single_open(file, video_proc_show, NULL);
594}
595
596static ssize_t video_proc_write(struct file *file, const char __user *buf,
597				size_t count, loff_t *pos)
598{
599	char *cmd, *buffer;
600	int value;
601	int remain = count;
602	int lcd_out = -1;
603	int crt_out = -1;
604	int tv_out = -1;
605	u32 hci_result;
606	u32 video_out;
607
608	cmd = kmalloc(count + 1, GFP_KERNEL);
609	if (!cmd)
610		return -ENOMEM;
611	if (copy_from_user(cmd, buf, count)) {
612		kfree(cmd);
613		return -EFAULT;
614	}
615	cmd[count] = '\0';
616
617	buffer = cmd;
618
619	/* scan expression.  Multiple expressions may be delimited with ;
620	 *
621	 *  NOTE: to keep scanning simple, invalid fields are ignored
622	 */
623	while (remain) {
624		if (sscanf(buffer, " lcd_out : %i", &value) == 1)
625			lcd_out = value & 1;
626		else if (sscanf(buffer, " crt_out : %i", &value) == 1)
627			crt_out = value & 1;
628		else if (sscanf(buffer, " tv_out : %i", &value) == 1)
629			tv_out = value & 1;
630		/* advance to one character past the next ; */
631		do {
632			++buffer;
633			--remain;
634		}
635		while (remain && *(buffer - 1) != ';');
636	}
637
638	kfree(cmd);
639
640	hci_read1(HCI_VIDEO_OUT, &video_out, &hci_result);
641	if (hci_result == HCI_SUCCESS) {
642		unsigned int new_video_out = video_out;
643		if (lcd_out != -1)
644			_set_bit(&new_video_out, HCI_VIDEO_OUT_LCD, lcd_out);
645		if (crt_out != -1)
646			_set_bit(&new_video_out, HCI_VIDEO_OUT_CRT, crt_out);
647		if (tv_out != -1)
648			_set_bit(&new_video_out, HCI_VIDEO_OUT_TV, tv_out);
649		/* To avoid unnecessary video disruption, only write the new
650		 * video setting if something changed. */
651		if (new_video_out != video_out)
652			write_acpi_int(METHOD_VIDEO_OUT, new_video_out);
653	} else {
654		return -EFAULT;
655	}
656
657	return count;
658}
659
660static const struct file_operations video_proc_fops = {
661	.owner		= THIS_MODULE,
662	.open		= video_proc_open,
663	.read		= seq_read,
664	.llseek		= seq_lseek,
665	.release	= single_release,
666	.write		= video_proc_write,
667};
668
669static int fan_proc_show(struct seq_file *m, void *v)
670{
671	u32 hci_result;
672	u32 value;
673
674	hci_read1(HCI_FAN, &value, &hci_result);
675	if (hci_result == HCI_SUCCESS) {
676		seq_printf(m, "running:                 %d\n", (value > 0));
677		seq_printf(m, "force_on:                %d\n", force_fan);
678	} else {
679		printk(MY_ERR "Error reading fan status\n");
680	}
681
682	return 0;
683}
684
685static int fan_proc_open(struct inode *inode, struct file *file)
686{
687	return single_open(file, fan_proc_show, NULL);
688}
689
690static ssize_t fan_proc_write(struct file *file, const char __user *buf,
691			      size_t count, loff_t *pos)
692{
693	char cmd[42];
694	size_t len;
695	int value;
696	u32 hci_result;
697
698	len = min(count, sizeof(cmd) - 1);
699	if (copy_from_user(cmd, buf, len))
700		return -EFAULT;
701	cmd[len] = '\0';
702
703	if (sscanf(cmd, " force_on : %i", &value) == 1 &&
704	    value >= 0 && value <= 1) {
705		hci_write1(HCI_FAN, value, &hci_result);
706		if (hci_result != HCI_SUCCESS)
707			return -EFAULT;
708		else
709			force_fan = value;
710	} else {
711		return -EINVAL;
712	}
713
714	return count;
715}
716
717static const struct file_operations fan_proc_fops = {
718	.owner		= THIS_MODULE,
719	.open		= fan_proc_open,
720	.read		= seq_read,
721	.llseek		= seq_lseek,
722	.release	= single_release,
723	.write		= fan_proc_write,
724};
725
726static int keys_proc_show(struct seq_file *m, void *v)
727{
728	u32 hci_result;
729	u32 value;
730
731	if (!key_event_valid) {
732		hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result);
733		if (hci_result == HCI_SUCCESS) {
734			key_event_valid = 1;
735			last_key_event = value;
736		} else if (hci_result == HCI_EMPTY) {
737			/* better luck next time */
738		} else if (hci_result == HCI_NOT_SUPPORTED) {
739			hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
740			printk(MY_NOTICE "Re-enabled hotkeys\n");
741		} else {
742			printk(MY_ERR "Error reading hotkey status\n");
743			goto end;
744		}
745	}
746
747	seq_printf(m, "hotkey_ready:            %d\n", key_event_valid);
748	seq_printf(m, "hotkey:                  0x%04x\n", last_key_event);
749end:
750	return 0;
751}
752
753static int keys_proc_open(struct inode *inode, struct file *file)
754{
755	return single_open(file, keys_proc_show, NULL);
756}
757
758static ssize_t keys_proc_write(struct file *file, const char __user *buf,
759			       size_t count, loff_t *pos)
760{
761	char cmd[42];
762	size_t len;
763	int value;
764
765	len = min(count, sizeof(cmd) - 1);
766	if (copy_from_user(cmd, buf, len))
767		return -EFAULT;
768	cmd[len] = '\0';
769
770	if (sscanf(cmd, " hotkey_ready : %i", &value) == 1 && value == 0) {
771		key_event_valid = 0;
772	} else {
773		return -EINVAL;
774	}
775
776	return count;
777}
778
779static const struct file_operations keys_proc_fops = {
780	.owner		= THIS_MODULE,
781	.open		= keys_proc_open,
782	.read		= seq_read,
783	.llseek		= seq_lseek,
784	.release	= single_release,
785	.write		= keys_proc_write,
786};
787
788static int version_proc_show(struct seq_file *m, void *v)
789{
790	seq_printf(m, "driver:                  %s\n", TOSHIBA_ACPI_VERSION);
791	seq_printf(m, "proc_interface:          %d\n", PROC_INTERFACE_VERSION);
792	return 0;
793}
794
795static int version_proc_open(struct inode *inode, struct file *file)
796{
797	return single_open(file, version_proc_show, PDE(inode)->data);
798}
799
800static const struct file_operations version_proc_fops = {
801	.owner		= THIS_MODULE,
802	.open		= version_proc_open,
803	.read		= seq_read,
804	.llseek		= seq_lseek,
805	.release	= single_release,
806};
807
808/* proc and module init
809 */
810
811#define PROC_TOSHIBA		"toshiba"
812
813static void __init create_toshiba_proc_entries(void)
814{
815	proc_create("lcd", S_IRUGO | S_IWUSR, toshiba_proc_dir, &lcd_proc_fops);
816	proc_create("video", S_IRUGO | S_IWUSR, toshiba_proc_dir, &video_proc_fops);
817	proc_create("fan", S_IRUGO | S_IWUSR, toshiba_proc_dir, &fan_proc_fops);
818	proc_create("keys", S_IRUGO | S_IWUSR, toshiba_proc_dir, &keys_proc_fops);
819	proc_create("version", S_IRUGO, toshiba_proc_dir, &version_proc_fops);
820}
821
822static void remove_toshiba_proc_entries(void)
823{
824	remove_proc_entry("lcd", toshiba_proc_dir);
825	remove_proc_entry("video", toshiba_proc_dir);
826	remove_proc_entry("fan", toshiba_proc_dir);
827	remove_proc_entry("keys", toshiba_proc_dir);
828	remove_proc_entry("version", toshiba_proc_dir);
829}
830
831static struct backlight_ops toshiba_backlight_data = {
832        .get_brightness = get_lcd,
833        .update_status  = set_lcd_status,
834};
835
836static struct key_entry *toshiba_acpi_get_entry_by_scancode(unsigned int code)
837{
838	struct key_entry *key;
839
840	for (key = toshiba_acpi_keymap; key->type != KE_END; key++)
841		if (code == key->code)
842			return key;
843
844	return NULL;
845}
846
847static struct key_entry *toshiba_acpi_get_entry_by_keycode(unsigned int code)
848{
849	struct key_entry *key;
850
851	for (key = toshiba_acpi_keymap; key->type != KE_END; key++)
852		if (code == key->keycode && key->type == KE_KEY)
853			return key;
854
855	return NULL;
856}
857
858static int toshiba_acpi_getkeycode(struct input_dev *dev,
859				   unsigned int scancode, unsigned int *keycode)
860{
861	struct key_entry *key = toshiba_acpi_get_entry_by_scancode(scancode);
862
863	if (key && key->type == KE_KEY) {
864		*keycode = key->keycode;
865		return 0;
866	}
867
868	return -EINVAL;
869}
870
871static int toshiba_acpi_setkeycode(struct input_dev *dev,
872				   unsigned int scancode, unsigned int keycode)
873{
874	struct key_entry *key;
875	unsigned int old_keycode;
876
877	key = toshiba_acpi_get_entry_by_scancode(scancode);
878	if (key && key->type == KE_KEY) {
879		old_keycode = key->keycode;
880		key->keycode = keycode;
881		set_bit(keycode, dev->keybit);
882		if (!toshiba_acpi_get_entry_by_keycode(old_keycode))
883			clear_bit(old_keycode, dev->keybit);
884		return 0;
885	}
886
887	return -EINVAL;
888}
889
890static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context)
891{
892	u32 hci_result, value;
893	struct key_entry *key;
894
895	if (event != 0x80)
896		return;
897	do {
898		hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result);
899		if (hci_result == HCI_SUCCESS) {
900			if (value == 0x100)
901				continue;
902			/* act on key press; ignore key release */
903			if (value & 0x80)
904				continue;
905
906			key = toshiba_acpi_get_entry_by_scancode
907				(value);
908			if (!key) {
909				printk(MY_INFO "Unknown key %x\n",
910				       value);
911				continue;
912			}
913			input_report_key(toshiba_acpi.hotkey_dev,
914					 key->keycode, 1);
915			input_sync(toshiba_acpi.hotkey_dev);
916			input_report_key(toshiba_acpi.hotkey_dev,
917					 key->keycode, 0);
918			input_sync(toshiba_acpi.hotkey_dev);
919		} else if (hci_result == HCI_NOT_SUPPORTED) {
920			hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
921			printk(MY_NOTICE "Re-enabled hotkeys\n");
922		}
923	} while (hci_result != HCI_EMPTY);
924}
925
926static int toshiba_acpi_setup_keyboard(char *device)
927{
928	acpi_status status;
929	acpi_handle handle;
930	int result;
931	const struct key_entry *key;
932
933	status = acpi_get_handle(NULL, device, &handle);
934	if (ACPI_FAILURE(status)) {
935		printk(MY_INFO "Unable to get notification device\n");
936		return -ENODEV;
937	}
938
939	toshiba_acpi.handle = handle;
940
941	status = acpi_evaluate_object(handle, "ENAB", NULL, NULL);
942	if (ACPI_FAILURE(status)) {
943		printk(MY_INFO "Unable to enable hotkeys\n");
944		return -ENODEV;
945	}
946
947	status = acpi_install_notify_handler(handle, ACPI_DEVICE_NOTIFY,
948					      toshiba_acpi_notify, NULL);
949	if (ACPI_FAILURE(status)) {
950		printk(MY_INFO "Unable to install hotkey notification\n");
951		return -ENODEV;
952	}
953
954	toshiba_acpi.hotkey_dev = input_allocate_device();
955	if (!toshiba_acpi.hotkey_dev) {
956		printk(MY_INFO "Unable to register input device\n");
957		return -ENOMEM;
958	}
959
960	toshiba_acpi.hotkey_dev->name = "Toshiba input device";
961	toshiba_acpi.hotkey_dev->phys = device;
962	toshiba_acpi.hotkey_dev->id.bustype = BUS_HOST;
963	toshiba_acpi.hotkey_dev->getkeycode = toshiba_acpi_getkeycode;
964	toshiba_acpi.hotkey_dev->setkeycode = toshiba_acpi_setkeycode;
965
966	for (key = toshiba_acpi_keymap; key->type != KE_END; key++) {
967		set_bit(EV_KEY, toshiba_acpi.hotkey_dev->evbit);
968		set_bit(key->keycode, toshiba_acpi.hotkey_dev->keybit);
969	}
970
971	result = input_register_device(toshiba_acpi.hotkey_dev);
972	if (result) {
973		printk(MY_INFO "Unable to register input device\n");
974		return result;
975	}
976
977	return 0;
978}
979
980static void toshiba_acpi_exit(void)
981{
982	if (toshiba_acpi.hotkey_dev)
983		input_unregister_device(toshiba_acpi.hotkey_dev);
984
985	if (toshiba_acpi.bt_rfk) {
986		rfkill_unregister(toshiba_acpi.bt_rfk);
987		rfkill_destroy(toshiba_acpi.bt_rfk);
988	}
989
990	if (toshiba_backlight_device)
991		backlight_device_unregister(toshiba_backlight_device);
992
993	remove_toshiba_proc_entries();
994
995	if (toshiba_proc_dir)
996		remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
997
998	acpi_remove_notify_handler(toshiba_acpi.handle, ACPI_DEVICE_NOTIFY,
999				   toshiba_acpi_notify);
1000
1001	if (toshiba_acpi.illumination_installed)
1002		led_classdev_unregister(&toshiba_led);
1003
1004	platform_device_unregister(toshiba_acpi.p_dev);
1005
1006	return;
1007}
1008
1009static int __init toshiba_acpi_init(void)
1010{
1011	u32 hci_result;
1012	bool bt_present;
1013	int ret = 0;
1014	struct backlight_properties props;
1015
1016	if (acpi_disabled)
1017		return -ENODEV;
1018
1019	/* simple device detection: look for HCI method */
1020	if (is_valid_acpi_path(TOSH_INTERFACE_1 GHCI_METHOD)) {
1021		method_hci = TOSH_INTERFACE_1 GHCI_METHOD;
1022		if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_1))
1023			printk(MY_INFO "Unable to activate hotkeys\n");
1024	} else if (is_valid_acpi_path(TOSH_INTERFACE_2 GHCI_METHOD)) {
1025		method_hci = TOSH_INTERFACE_2 GHCI_METHOD;
1026		if (toshiba_acpi_setup_keyboard(TOSH_INTERFACE_2))
1027			printk(MY_INFO "Unable to activate hotkeys\n");
1028	} else
1029		return -ENODEV;
1030
1031	printk(MY_INFO "Toshiba Laptop ACPI Extras version %s\n",
1032	       TOSHIBA_ACPI_VERSION);
1033	printk(MY_INFO "    HCI method: %s\n", method_hci);
1034
1035	mutex_init(&toshiba_acpi.mutex);
1036
1037	toshiba_acpi.p_dev = platform_device_register_simple("toshiba_acpi",
1038							      -1, NULL, 0);
1039	if (IS_ERR(toshiba_acpi.p_dev)) {
1040		ret = PTR_ERR(toshiba_acpi.p_dev);
1041		printk(MY_ERR "unable to register platform device\n");
1042		toshiba_acpi.p_dev = NULL;
1043		toshiba_acpi_exit();
1044		return ret;
1045	}
1046
1047	force_fan = 0;
1048	key_event_valid = 0;
1049
1050	/* enable event fifo */
1051	hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
1052
1053	toshiba_proc_dir = proc_mkdir(PROC_TOSHIBA, acpi_root_dir);
1054	if (!toshiba_proc_dir) {
1055		toshiba_acpi_exit();
1056		return -ENODEV;
1057	} else {
1058		create_toshiba_proc_entries();
1059	}
1060
1061	props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
1062	toshiba_backlight_device = backlight_device_register("toshiba",
1063							     &toshiba_acpi.p_dev->dev,
1064							     NULL,
1065							     &toshiba_backlight_data,
1066							     &props);
1067        if (IS_ERR(toshiba_backlight_device)) {
1068		ret = PTR_ERR(toshiba_backlight_device);
1069
1070		printk(KERN_ERR "Could not register toshiba backlight device\n");
1071		toshiba_backlight_device = NULL;
1072		toshiba_acpi_exit();
1073		return ret;
1074	}
1075
1076	/* Register rfkill switch for Bluetooth */
1077	if (hci_get_bt_present(&bt_present) == HCI_SUCCESS && bt_present) {
1078		toshiba_acpi.bt_rfk = rfkill_alloc(toshiba_acpi.bt_name,
1079						   &toshiba_acpi.p_dev->dev,
1080						   RFKILL_TYPE_BLUETOOTH,
1081						   &toshiba_rfk_ops,
1082						   &toshiba_acpi);
1083		if (!toshiba_acpi.bt_rfk) {
1084			printk(MY_ERR "unable to allocate rfkill device\n");
1085			toshiba_acpi_exit();
1086			return -ENOMEM;
1087		}
1088
1089		ret = rfkill_register(toshiba_acpi.bt_rfk);
1090		if (ret) {
1091			printk(MY_ERR "unable to register rfkill device\n");
1092			rfkill_destroy(toshiba_acpi.bt_rfk);
1093			toshiba_acpi_exit();
1094			return ret;
1095		}
1096	}
1097
1098	toshiba_acpi.illumination_installed = 0;
1099	if (toshiba_illumination_available()) {
1100		if (!led_classdev_register(&(toshiba_acpi.p_dev->dev),
1101					   &toshiba_led))
1102			toshiba_acpi.illumination_installed = 1;
1103	}
1104
1105	return 0;
1106}
1107
1108module_init(toshiba_acpi_init);
1109module_exit(toshiba_acpi_exit);
1110