2 * Sony Programmable I/O Control Device driver for VAIO
4 * Copyright (C) 2001-2003 Stelian Pop <stelian@popies.net>
6 * Copyright (C) 2001-2002 AlcĂ´ve <www.alcove.com>
8 * Copyright (C) 2001 Michael Ashley <m.ashley@unsw.edu.au>
10 * Copyright (C) 2001 Junichi Morita <jun1m@mars.dti.ne.jp>
12 * Copyright (C) 2000 Takaya Kinjo <t-kinjo@tc4.so-net.ne.jp>
14 * Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com>
16 * Earlier work by Werner Almesberger, Paul `Rusty' Russell and Paul Mackerras.
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
34 #include <linux/config.h>
35 #include <linux/module.h>
36 #include <linux/input.h>
37 #include <linux/pci.h>
38 #include <linux/sched.h>
39 #include <linux/init.h>
40 #include <linux/interrupt.h>
41 #include <linux/miscdevice.h>
42 #include <linux/poll.h>
43 #include <linux/delay.h>
44 #include <linux/wait.h>
45 #include <linux/acpi.h>
46 #include <linux/dmi.h>
47 #include <linux/sysdev.h>
49 #include <asm/uaccess.h>
51 #include <asm/system.h>
53 static int verbose
; /* = 0 */
56 #include <linux/sonypi.h>
58 static struct sonypi_device sonypi_device
;
59 static int minor
= -1;
60 static int fnkeyinit
; /* = 0 */
61 static int camera
; /* = 0 */
62 static int compat
; /* = 0 */
63 static int useinput
= 1;
64 static unsigned long mask
= 0xffffffff;
67 static inline void sonypi_initq(void) {
68 sonypi_device
.queue
.head
= sonypi_device
.queue
.tail
= 0;
69 sonypi_device
.queue
.len
= 0;
70 sonypi_device
.queue
.s_lock
= SPIN_LOCK_UNLOCKED
;
71 init_waitqueue_head(&sonypi_device
.queue
.proc_list
);
74 /* Pulls an event from the queue */
75 static inline unsigned char sonypi_pullq(void) {
79 spin_lock_irqsave(&sonypi_device
.queue
.s_lock
, flags
);
80 if (!sonypi_device
.queue
.len
) {
81 spin_unlock_irqrestore(&sonypi_device
.queue
.s_lock
, flags
);
84 result
= sonypi_device
.queue
.buf
[sonypi_device
.queue
.head
];
85 sonypi_device
.queue
.head
++;
86 sonypi_device
.queue
.head
&= (SONYPI_BUF_SIZE
- 1);
87 sonypi_device
.queue
.len
--;
88 spin_unlock_irqrestore(&sonypi_device
.queue
.s_lock
, flags
);
92 /* Pushes an event into the queue */
93 static inline void sonypi_pushq(unsigned char event
) {
96 spin_lock_irqsave(&sonypi_device
.queue
.s_lock
, flags
);
97 if (sonypi_device
.queue
.len
== SONYPI_BUF_SIZE
) {
98 /* remove the first element */
99 sonypi_device
.queue
.head
++;
100 sonypi_device
.queue
.head
&= (SONYPI_BUF_SIZE
- 1);
101 sonypi_device
.queue
.len
--;
103 sonypi_device
.queue
.buf
[sonypi_device
.queue
.tail
] = event
;
104 sonypi_device
.queue
.tail
++;
105 sonypi_device
.queue
.tail
&= (SONYPI_BUF_SIZE
- 1);
106 sonypi_device
.queue
.len
++;
108 kill_fasync(&sonypi_device
.queue
.fasync
, SIGIO
, POLL_IN
);
109 wake_up_interruptible(&sonypi_device
.queue
.proc_list
);
110 spin_unlock_irqrestore(&sonypi_device
.queue
.s_lock
, flags
);
113 /* Tests if the queue is empty */
114 static inline int sonypi_emptyq(void) {
118 spin_lock_irqsave(&sonypi_device
.queue
.s_lock
, flags
);
119 result
= (sonypi_device
.queue
.len
== 0);
120 spin_unlock_irqrestore(&sonypi_device
.queue
.s_lock
, flags
);
124 static int ec_read16(u8 addr
, u16
*value
) {
126 if (sonypi_ec_read(addr
, &val_lb
))
128 if (sonypi_ec_read(addr
+ 1, &val_hb
))
130 *value
= val_lb
| (val_hb
<< 8);
134 /* Initializes the device - this comes from the AML code in the ACPI bios */
135 static void sonypi_type1_srs(void) {
138 pci_read_config_dword(sonypi_device
.dev
, SONYPI_G10A
, &v
);
139 v
= (v
& 0xFFFF0000) | ((u32
)sonypi_device
.ioport1
);
140 pci_write_config_dword(sonypi_device
.dev
, SONYPI_G10A
, v
);
142 pci_read_config_dword(sonypi_device
.dev
, SONYPI_G10A
, &v
);
143 v
= (v
& 0xFFF0FFFF) |
144 (((u32
)sonypi_device
.ioport1
^ sonypi_device
.ioport2
) << 16);
145 pci_write_config_dword(sonypi_device
.dev
, SONYPI_G10A
, v
);
147 v
= inl(SONYPI_IRQ_PORT
);
148 v
&= ~(((u32
)0x3) << SONYPI_IRQ_SHIFT
);
149 v
|= (((u32
)sonypi_device
.bits
) << SONYPI_IRQ_SHIFT
);
150 outl(v
, SONYPI_IRQ_PORT
);
152 pci_read_config_dword(sonypi_device
.dev
, SONYPI_G10A
, &v
);
153 v
= (v
& 0xFF1FFFFF) | 0x00C00000;
154 pci_write_config_dword(sonypi_device
.dev
, SONYPI_G10A
, v
);
157 static void sonypi_type2_srs(void) {
158 if (sonypi_ec_write(SONYPI_SHIB
, (sonypi_device
.ioport1
& 0xFF00) >> 8))
159 printk(KERN_WARNING
"ec_write failed\n");
160 if (sonypi_ec_write(SONYPI_SLOB
, sonypi_device
.ioport1
& 0x00FF))
161 printk(KERN_WARNING
"ec_write failed\n");
162 if (sonypi_ec_write(SONYPI_SIRQ
, sonypi_device
.bits
))
163 printk(KERN_WARNING
"ec_write failed\n");
167 /* Disables the device - this comes from the AML code in the ACPI bios */
168 static void sonypi_type1_dis(void) {
171 pci_read_config_dword(sonypi_device
.dev
, SONYPI_G10A
, &v
);
173 pci_write_config_dword(sonypi_device
.dev
, SONYPI_G10A
, v
);
175 v
= inl(SONYPI_IRQ_PORT
);
176 v
|= (0x3 << SONYPI_IRQ_SHIFT
);
177 outl(v
, SONYPI_IRQ_PORT
);
180 static void sonypi_type2_dis(void) {
181 if (sonypi_ec_write(SONYPI_SHIB
, 0))
182 printk(KERN_WARNING
"ec_write failed\n");
183 if (sonypi_ec_write(SONYPI_SLOB
, 0))
184 printk(KERN_WARNING
"ec_write failed\n");
185 if (sonypi_ec_write(SONYPI_SIRQ
, 0))
186 printk(KERN_WARNING
"ec_write failed\n");
189 static u8
sonypi_call1(u8 dev
) {
192 wait_on_command(0, inb_p(sonypi_device
.ioport2
) & 2, ITERATIONS_LONG
);
193 outb(dev
, sonypi_device
.ioport2
);
194 v1
= inb_p(sonypi_device
.ioport2
);
195 v2
= inb_p(sonypi_device
.ioport1
);
199 static u8
sonypi_call2(u8 dev
, u8 fn
) {
202 wait_on_command(0, inb_p(sonypi_device
.ioport2
) & 2, ITERATIONS_LONG
);
203 outb(dev
, sonypi_device
.ioport2
);
204 wait_on_command(0, inb_p(sonypi_device
.ioport2
) & 2, ITERATIONS_LONG
);
205 outb(fn
, sonypi_device
.ioport1
);
206 v1
= inb_p(sonypi_device
.ioport1
);
210 static u8
sonypi_call3(u8 dev
, u8 fn
, u8 v
) {
213 wait_on_command(0, inb_p(sonypi_device
.ioport2
) & 2, ITERATIONS_LONG
);
214 outb(dev
, sonypi_device
.ioport2
);
215 wait_on_command(0, inb_p(sonypi_device
.ioport2
) & 2, ITERATIONS_LONG
);
216 outb(fn
, sonypi_device
.ioport1
);
217 wait_on_command(0, inb_p(sonypi_device
.ioport2
) & 2, ITERATIONS_LONG
);
218 outb(v
, sonypi_device
.ioport1
);
219 v1
= inb_p(sonypi_device
.ioport1
);
223 static u8
sonypi_read(u8 fn
) {
228 v1
= sonypi_call2(0x8f, fn
);
229 v2
= sonypi_call2(0x8f, fn
);
230 if (v1
== v2
&& v1
!= 0xff)
236 /* Set brightness, hue etc */
237 static void sonypi_set(u8 fn
, u8 v
) {
239 wait_on_command(0, sonypi_call3(0x90, fn
, v
), ITERATIONS_SHORT
);
242 /* Tests if the camera is ready */
243 static int sonypi_camera_ready(void) {
246 v
= sonypi_call2(0x8f, SONYPI_CAMERA_STATUS
);
247 return (v
!= 0xff && (v
& SONYPI_CAMERA_STATUS_READY
));
250 /* Turns the camera off */
251 static void sonypi_camera_off(void) {
253 sonypi_set(SONYPI_CAMERA_PICTURE
, SONYPI_CAMERA_MUTE_MASK
);
255 if (!sonypi_device
.camera_power
)
258 sonypi_call2(0x91, 0);
259 sonypi_device
.camera_power
= 0;
262 /* Turns the camera on */
263 static void sonypi_camera_on(void) {
266 if (sonypi_device
.camera_power
)
269 for (j
= 5; j
> 0; j
--) {
271 while (sonypi_call2(0x91, 0x1)) {
272 set_current_state(TASK_UNINTERRUPTIBLE
);
277 for (i
= 400; i
> 0; i
--) {
278 if (sonypi_camera_ready())
280 set_current_state(TASK_UNINTERRUPTIBLE
);
288 printk(KERN_WARNING
"sonypi: failed to power on camera\n");
292 sonypi_set(0x10, 0x5a);
293 sonypi_device
.camera_power
= 1;
296 /* sets the bluetooth subsystem power state */
297 static void sonypi_setbluetoothpower(u8 state
) {
300 if (sonypi_device
.bluetooth_power
== state
)
303 sonypi_call2(0x96, state
);
305 sonypi_device
.bluetooth_power
= state
;
308 /* Interrupt handler: some event is available */
309 static irqreturn_t
sonypi_irq(int irq
, void *dev_id
, struct pt_regs
*regs
) {
310 u8 v1
, v2
, event
= 0;
313 v1
= inb_p(sonypi_device
.ioport1
);
314 v2
= inb_p(sonypi_device
.ioport1
+ sonypi_device
.evtype_offset
);
316 for (i
= 0; sonypi_eventtypes
[i
].model
; i
++) {
317 if (sonypi_device
.model
!= sonypi_eventtypes
[i
].model
)
319 if ((v2
& sonypi_eventtypes
[i
].data
) != sonypi_eventtypes
[i
].data
)
321 if (! (mask
& sonypi_eventtypes
[i
].mask
))
323 for (j
= 0; sonypi_eventtypes
[i
].events
[j
].event
; j
++) {
324 if (v1
== sonypi_eventtypes
[i
].events
[j
].data
) {
325 event
= sonypi_eventtypes
[i
].events
[j
].event
;
333 "sonypi: unknown event port1=0x%02x,port2=0x%02x\n",v1
,v2
);
334 /* We need to return IRQ_HANDLED here because there *are*
335 * events belonging to the sonypi device we don't know about,
336 * but we still don't want those to pollute the logs... */
342 "sonypi: event port1=0x%02x,port2=0x%02x\n", v1
, v2
);
344 #ifdef SONYPI_USE_INPUT
346 struct input_dev
*jog_dev
= &sonypi_device
.jog_dev
;
347 if (event
== SONYPI_EVENT_JOGDIAL_PRESSED
)
348 input_report_key(jog_dev
, BTN_MIDDLE
, 1);
349 else if (event
== SONYPI_EVENT_ANYBUTTON_RELEASED
)
350 input_report_key(jog_dev
, BTN_MIDDLE
, 0);
351 else if ((event
== SONYPI_EVENT_JOGDIAL_UP
) ||
352 (event
== SONYPI_EVENT_JOGDIAL_UP_PRESSED
))
353 input_report_rel(jog_dev
, REL_WHEEL
, 1);
354 else if ((event
== SONYPI_EVENT_JOGDIAL_DOWN
) ||
355 (event
== SONYPI_EVENT_JOGDIAL_DOWN_PRESSED
))
356 input_report_rel(jog_dev
, REL_WHEEL
, -1);
359 #endif /* SONYPI_USE_INPUT */
364 /* External camera command (exported to the motion eye v4l driver) */
365 u8
sonypi_camera_command(int command
, u8 value
) {
371 down(&sonypi_device
.lock
);
374 case SONYPI_COMMAND_GETCAMERA
:
375 ret
= sonypi_camera_ready();
377 case SONYPI_COMMAND_SETCAMERA
:
383 case SONYPI_COMMAND_GETCAMERABRIGHTNESS
:
384 ret
= sonypi_read(SONYPI_CAMERA_BRIGHTNESS
);
386 case SONYPI_COMMAND_SETCAMERABRIGHTNESS
:
387 sonypi_set(SONYPI_CAMERA_BRIGHTNESS
, value
);
389 case SONYPI_COMMAND_GETCAMERACONTRAST
:
390 ret
= sonypi_read(SONYPI_CAMERA_CONTRAST
);
392 case SONYPI_COMMAND_SETCAMERACONTRAST
:
393 sonypi_set(SONYPI_CAMERA_CONTRAST
, value
);
395 case SONYPI_COMMAND_GETCAMERAHUE
:
396 ret
= sonypi_read(SONYPI_CAMERA_HUE
);
398 case SONYPI_COMMAND_SETCAMERAHUE
:
399 sonypi_set(SONYPI_CAMERA_HUE
, value
);
401 case SONYPI_COMMAND_GETCAMERACOLOR
:
402 ret
= sonypi_read(SONYPI_CAMERA_COLOR
);
404 case SONYPI_COMMAND_SETCAMERACOLOR
:
405 sonypi_set(SONYPI_CAMERA_COLOR
, value
);
407 case SONYPI_COMMAND_GETCAMERASHARPNESS
:
408 ret
= sonypi_read(SONYPI_CAMERA_SHARPNESS
);
410 case SONYPI_COMMAND_SETCAMERASHARPNESS
:
411 sonypi_set(SONYPI_CAMERA_SHARPNESS
, value
);
413 case SONYPI_COMMAND_GETCAMERAPICTURE
:
414 ret
= sonypi_read(SONYPI_CAMERA_PICTURE
);
416 case SONYPI_COMMAND_SETCAMERAPICTURE
:
417 sonypi_set(SONYPI_CAMERA_PICTURE
, value
);
419 case SONYPI_COMMAND_GETCAMERAAGC
:
420 ret
= sonypi_read(SONYPI_CAMERA_AGC
);
422 case SONYPI_COMMAND_SETCAMERAAGC
:
423 sonypi_set(SONYPI_CAMERA_AGC
, value
);
425 case SONYPI_COMMAND_GETCAMERADIRECTION
:
426 ret
= sonypi_read(SONYPI_CAMERA_STATUS
);
427 ret
&= SONYPI_DIRECTION_BACKWARDS
;
429 case SONYPI_COMMAND_GETCAMERAROMVERSION
:
430 ret
= sonypi_read(SONYPI_CAMERA_ROMVERSION
);
432 case SONYPI_COMMAND_GETCAMERAREVISION
:
433 ret
= sonypi_read(SONYPI_CAMERA_REVISION
);
436 up(&sonypi_device
.lock
);
440 static int sonypi_misc_fasync(int fd
, struct file
*filp
, int on
) {
443 retval
= fasync_helper(fd
, filp
, on
, &sonypi_device
.queue
.fasync
);
449 static int sonypi_misc_release(struct inode
* inode
, struct file
* file
) {
450 sonypi_misc_fasync(-1, file
, 0);
451 down(&sonypi_device
.lock
);
452 sonypi_device
.open_count
--;
453 up(&sonypi_device
.lock
);
457 static int sonypi_misc_open(struct inode
* inode
, struct file
* file
) {
458 down(&sonypi_device
.lock
);
459 /* Flush input queue on first open */
460 if (!sonypi_device
.open_count
)
462 sonypi_device
.open_count
++;
463 up(&sonypi_device
.lock
);
467 static ssize_t
sonypi_misc_read(struct file
* file
, char __user
* buf
,
468 size_t count
, loff_t
*pos
)
470 DECLARE_WAITQUEUE(wait
, current
);
474 if (sonypi_emptyq()) {
475 if (file
->f_flags
& O_NONBLOCK
)
477 add_wait_queue(&sonypi_device
.queue
.proc_list
, &wait
);
479 set_current_state(TASK_INTERRUPTIBLE
);
480 if (sonypi_emptyq() && !signal_pending(current
)) {
484 current
->state
= TASK_RUNNING
;
485 remove_wait_queue(&sonypi_device
.queue
.proc_list
, &wait
);
487 while (i
> 0 && !sonypi_emptyq()) {
493 file
->f_dentry
->d_inode
->i_atime
= CURRENT_TIME
;
496 if (signal_pending(current
))
501 static unsigned int sonypi_misc_poll(struct file
*file
, poll_table
* wait
) {
502 poll_wait(file
, &sonypi_device
.queue
.proc_list
, wait
);
503 if (!sonypi_emptyq())
504 return POLLIN
| POLLRDNORM
;
508 static int sonypi_misc_ioctl(struct inode
*ip
, struct file
*fp
,
509 unsigned int cmd
, unsigned long arg
) {
511 void __user
*argp
= (void __user
*)arg
;
515 down(&sonypi_device
.lock
);
518 if (sonypi_ec_read(SONYPI_LCD_LIGHT
, &val8
)) {
522 if (copy_to_user(argp
, &val8
, sizeof(val8
)))
526 if (copy_from_user(&val8
, argp
, sizeof(val8
))) {
530 if (sonypi_ec_write(SONYPI_LCD_LIGHT
, val8
))
533 case SONYPI_IOCGBAT1CAP
:
534 if (ec_read16(SONYPI_BAT1_FULL
, &val16
)) {
538 if (copy_to_user(argp
, &val16
, sizeof(val16
)))
541 case SONYPI_IOCGBAT1REM
:
542 if (ec_read16(SONYPI_BAT1_LEFT
, &val16
)) {
546 if (copy_to_user(argp
, &val16
, sizeof(val16
)))
549 case SONYPI_IOCGBAT2CAP
:
550 if (ec_read16(SONYPI_BAT2_FULL
, &val16
)) {
554 if (copy_to_user(argp
, &val16
, sizeof(val16
)))
557 case SONYPI_IOCGBAT2REM
:
558 if (ec_read16(SONYPI_BAT2_LEFT
, &val16
)) {
562 if (copy_to_user(argp
, &val16
, sizeof(val16
)))
565 case SONYPI_IOCGBATFLAGS
:
566 if (sonypi_ec_read(SONYPI_BAT_FLAGS
, &val8
)) {
571 if (copy_to_user(argp
, &val8
, sizeof(val8
)))
574 case SONYPI_IOCGBLUE
:
575 val8
= sonypi_device
.bluetooth_power
;
576 if (copy_to_user(argp
, &val8
, sizeof(val8
)))
579 case SONYPI_IOCSBLUE
:
580 if (copy_from_user(&val8
, argp
, sizeof(val8
))) {
584 sonypi_setbluetoothpower(val8
);
589 up(&sonypi_device
.lock
);
593 static struct file_operations sonypi_misc_fops
= {
594 .owner
= THIS_MODULE
,
595 .read
= sonypi_misc_read
,
596 .poll
= sonypi_misc_poll
,
597 .open
= sonypi_misc_open
,
598 .release
= sonypi_misc_release
,
599 .fasync
= sonypi_misc_fasync
,
600 .ioctl
= sonypi_misc_ioctl
,
603 struct miscdevice sonypi_misc_device
= {
604 -1, "sonypi", &sonypi_misc_fops
608 static int old_camera_power
;
610 static int sonypi_suspend(struct sys_device
*dev
, u32 state
) {
611 sonypi_call2(0x81, 0); /* make sure we don't get any more events */
613 old_camera_power
= sonypi_device
.camera_power
;
616 if (sonypi_device
.model
== SONYPI_DEVICE_MODEL_TYPE2
)
620 /* disable ACPI mode */
621 if (!SONYPI_ACPI_ACTIVE
&& fnkeyinit
)
626 static int sonypi_resume(struct sys_device
*dev
) {
627 /* Enable ACPI mode to get Fn key events */
628 if (!SONYPI_ACPI_ACTIVE
&& fnkeyinit
)
630 if (sonypi_device
.model
== SONYPI_DEVICE_MODEL_TYPE2
)
635 sonypi_call2(0x81, 0xff);
640 if (camera
&& old_camera_power
)
646 static int sonypi_pm_callback(struct pm_dev
*dev
, pm_request_t rqst
, void *data
) {
650 sonypi_suspend(NULL
, 0);
659 /* New PM scheme (device model) */
660 static struct sysdev_class sonypi_sysclass
= {
661 set_kset_name("sonypi"),
662 .suspend
= sonypi_suspend
,
663 .resume
= sonypi_resume
,
666 static struct sys_device sonypi_sysdev
= {
668 .cls
= &sonypi_sysclass
,
672 static int __devinit
sonypi_probe(struct pci_dev
*pcidev
) {
674 struct sonypi_ioport_list
*ioport_list
;
675 struct sonypi_irq_list
*irq_list
;
677 sonypi_device
.dev
= pcidev
;
679 sonypi_device
.model
= SONYPI_DEVICE_MODEL_TYPE1
;
681 sonypi_device
.model
= SONYPI_DEVICE_MODEL_TYPE2
;
683 init_MUTEX(&sonypi_device
.lock
);
684 sonypi_device
.bluetooth_power
= 0;
686 if (pcidev
&& pci_enable_device(pcidev
)) {
687 printk(KERN_ERR
"sonypi: pci_enable_device failed\n");
692 sonypi_misc_device
.minor
= (minor
== -1) ?
693 MISC_DYNAMIC_MINOR
: minor
;
694 if ((ret
= misc_register(&sonypi_misc_device
))) {
695 printk(KERN_ERR
"sonypi: misc_register failed\n");
699 if (sonypi_device
.model
== SONYPI_DEVICE_MODEL_TYPE2
) {
700 ioport_list
= sonypi_type2_ioport_list
;
701 sonypi_device
.region_size
= SONYPI_TYPE2_REGION_SIZE
;
702 sonypi_device
.evtype_offset
= SONYPI_TYPE2_EVTYPE_OFFSET
;
703 irq_list
= sonypi_type2_irq_list
;
706 ioport_list
= sonypi_type1_ioport_list
;
707 sonypi_device
.region_size
= SONYPI_TYPE1_REGION_SIZE
;
708 sonypi_device
.evtype_offset
= SONYPI_TYPE1_EVTYPE_OFFSET
;
709 irq_list
= sonypi_type1_irq_list
;
712 for (i
= 0; ioport_list
[i
].port1
; i
++) {
713 if (request_region(ioport_list
[i
].port1
,
714 sonypi_device
.region_size
,
715 "Sony Programable I/O Device")) {
717 sonypi_device
.ioport1
= ioport_list
[i
].port1
;
718 sonypi_device
.ioport2
= ioport_list
[i
].port2
;
722 if (!sonypi_device
.ioport1
) {
723 printk(KERN_ERR
"sonypi: request_region failed\n");
728 for (i
= 0; irq_list
[i
].irq
; i
++) {
730 sonypi_device
.irq
= irq_list
[i
].irq
;
731 sonypi_device
.bits
= irq_list
[i
].bits
;
733 /* Enable sonypi IRQ settings */
734 if (sonypi_device
.model
== SONYPI_DEVICE_MODEL_TYPE2
)
740 sonypi_call2(0x81, 0xff);
746 /* Now try requesting the irq from the system */
747 if (!request_irq(sonypi_device
.irq
, sonypi_irq
,
748 SA_SHIRQ
, "sonypi", sonypi_irq
))
751 /* If request_irq failed, disable sonypi IRQ settings */
752 if (sonypi_device
.model
== SONYPI_DEVICE_MODEL_TYPE2
)
758 if (!irq_list
[i
].irq
) {
759 printk(KERN_ERR
"sonypi: request_irq failed\n");
765 sonypi_device
.pm
= pm_register(PM_PCI_DEV
, 0, sonypi_pm_callback
);
767 if (sysdev_class_register(&sonypi_sysclass
) != 0) {
768 printk(KERN_ERR
"sonypi: sysdev_class_register failed\n");
772 if (sysdev_register(&sonypi_sysdev
) != 0) {
773 printk(KERN_ERR
"sonypi: sysdev_register failed\n");
779 /* Enable ACPI mode to get Fn key events */
780 if (!SONYPI_ACPI_ACTIVE
&& fnkeyinit
)
783 printk(KERN_INFO
"sonypi: Sony Programmable I/O Controller Driver v%d.%d.\n",
784 SONYPI_DRIVER_MAJORVERSION
,
785 SONYPI_DRIVER_MINORVERSION
);
786 printk(KERN_INFO
"sonypi: detected %s model, "
787 "verbose = %d, fnkeyinit = %s, camera = %s, "
788 "compat = %s, mask = 0x%08lx, useinput = %s, acpi = %s\n",
789 (sonypi_device
.model
== SONYPI_DEVICE_MODEL_TYPE1
) ?
792 fnkeyinit
? "on" : "off",
793 camera
? "on" : "off",
794 compat
? "on" : "off",
796 useinput
? "on" : "off",
797 SONYPI_ACPI_ACTIVE
? "on" : "off");
798 printk(KERN_INFO
"sonypi: enabled at irq=%d, port1=0x%x, port2=0x%x\n",
800 sonypi_device
.ioport1
, sonypi_device
.ioport2
);
803 printk(KERN_INFO
"sonypi: device allocated minor is %d\n",
804 sonypi_misc_device
.minor
);
806 #ifdef SONYPI_USE_INPUT
808 /* Initialize the Input Drivers: */
809 sonypi_device
.jog_dev
.evbit
[0] = BIT(EV_KEY
) | BIT(EV_REL
);
810 sonypi_device
.jog_dev
.keybit
[LONG(BTN_MOUSE
)] = BIT(BTN_MIDDLE
);
811 sonypi_device
.jog_dev
.relbit
[0] = BIT(REL_WHEEL
);
812 sonypi_device
.jog_dev
.name
= (char *) kmalloc(
813 sizeof(SONYPI_INPUTNAME
), GFP_KERNEL
);
814 sprintf(sonypi_device
.jog_dev
.name
, SONYPI_INPUTNAME
);
815 sonypi_device
.jog_dev
.id
.bustype
= BUS_ISA
;
816 sonypi_device
.jog_dev
.id
.vendor
= PCI_VENDOR_ID_SONY
;
818 input_register_device(&sonypi_device
.jog_dev
);
819 printk(KERN_INFO
"%s installed.\n", sonypi_device
.jog_dev
.name
);
821 #endif /* SONYPI_USE_INPUT */
827 sysdev_class_unregister(&sonypi_sysclass
);
829 free_irq(sonypi_device
.irq
, sonypi_irq
);
832 release_region(sonypi_device
.ioport1
, sonypi_device
.region_size
);
834 misc_deregister(&sonypi_misc_device
);
839 static void __devexit
sonypi_remove(void) {
842 pm_unregister(sonypi_device
.pm
);
844 sysdev_unregister(&sonypi_sysdev
);
845 sysdev_class_unregister(&sonypi_sysclass
);
848 sonypi_call2(0x81, 0); /* make sure we don't get any more events */
850 #ifdef SONYPI_USE_INPUT
852 input_unregister_device(&sonypi_device
.jog_dev
);
853 kfree(sonypi_device
.jog_dev
.name
);
855 #endif /* SONYPI_USE_INPUT */
859 if (sonypi_device
.model
== SONYPI_DEVICE_MODEL_TYPE2
)
863 /* disable ACPI mode */
864 if (!SONYPI_ACPI_ACTIVE
&& fnkeyinit
)
866 free_irq(sonypi_device
.irq
, sonypi_irq
);
867 release_region(sonypi_device
.ioport1
, sonypi_device
.region_size
);
868 misc_deregister(&sonypi_misc_device
);
869 printk(KERN_INFO
"sonypi: removed.\n");
872 static struct dmi_system_id __initdata sonypi_dmi_table
[] = {
874 .ident
= "Sony Vaio",
876 DMI_MATCH(DMI_SYS_VENDOR
, "Sony Corporation"),
877 DMI_MATCH(DMI_PRODUCT_NAME
, "PCG-"),
881 .ident
= "Sony Vaio",
883 DMI_MATCH(DMI_SYS_VENDOR
, "Sony Corporation"),
884 DMI_MATCH(DMI_PRODUCT_NAME
, "VGN-"),
890 static int __init
sonypi_init_module(void)
892 struct pci_dev
*pcidev
= NULL
;
893 if (dmi_check_system(sonypi_dmi_table
)) {
894 pcidev
= pci_find_device(PCI_VENDOR_ID_INTEL
,
895 PCI_DEVICE_ID_INTEL_82371AB_3
,
897 return sonypi_probe(pcidev
);
903 static void __exit
sonypi_cleanup_module(void) {
908 static int __init
sonypi_setup(char *str
) {
911 str
= get_options(str
, ARRAY_SIZE(ints
), ints
);
937 __setup("sonypi=", sonypi_setup
);
940 /* Module entry points */
941 module_init(sonypi_init_module
);
942 module_exit(sonypi_cleanup_module
);
944 MODULE_AUTHOR("Stelian Pop <stelian@popies.net>");
945 MODULE_DESCRIPTION("Sony Programmable I/O Control Device driver");
946 MODULE_LICENSE("GPL");
949 MODULE_PARM(minor
,"i");
950 MODULE_PARM_DESC(minor
, "minor number of the misc device, default is -1 (automatic)");
951 MODULE_PARM(verbose
,"i");
952 MODULE_PARM_DESC(verbose
, "be verbose, default is 0 (no)");
953 MODULE_PARM(fnkeyinit
,"i");
954 MODULE_PARM_DESC(fnkeyinit
, "set this if your Fn keys do not generate any event");
955 MODULE_PARM(camera
,"i");
956 MODULE_PARM_DESC(camera
, "set this if you have a MotionEye camera (PictureBook series)");
957 MODULE_PARM(compat
,"i");
958 MODULE_PARM_DESC(compat
, "set this if you want to enable backward compatibility mode");
959 MODULE_PARM(mask
, "i");
960 MODULE_PARM_DESC(mask
, "set this to the mask of event you want to enable (see doc)");
961 MODULE_PARM(useinput
, "i");
962 MODULE_PARM_DESC(useinput
, "if you have a jogdial, set this if you would like it to use the modern Linux Input Driver system");
964 EXPORT_SYMBOL(sonypi_camera_command
);