OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [sonypi.c] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * Sony Programmable I/O Control Device driver for VAIO
3
 *
4
 * Copyright (C) 2001-2003 Stelian Pop <stelian@popies.net>
5
 *
6
 * Copyright (C) 2001-2002 Alcôve <www.alcove.com>
7
 *
8
 * Copyright (C) 2001 Michael Ashley <m.ashley@unsw.edu.au>
9
 *
10
 * Copyright (C) 2001 Junichi Morita <jun1m@mars.dti.ne.jp>
11
 *
12
 * Copyright (C) 2000 Takaya Kinjo <t-kinjo@tc4.so-net.ne.jp>
13
 *
14
 * Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com>
15
 *
16
 * Earlier work by Werner Almesberger, Paul `Rusty' Russell and Paul Mackerras.
17
 *
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.
22
 *
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.
27
 *
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.
31
 *
32
 */
33
 
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
 
47
#include <asm/uaccess.h>
48
#include <asm/io.h>
49
#include <asm/system.h>
50
 
51
#include "sonypi.h"
52
#include <linux/sonypi.h>
53
 
54
static struct sonypi_device sonypi_device;
55
static int minor = -1;
56
static int verbose; /* = 0 */
57
static int fnkeyinit; /* = 0 */
58
static int camera; /* = 0 */
59
static int compat; /* = 0 */
60
static int useinput = 1;
61
static unsigned long mask = 0xffffffff;
62
 
63
/* Inits the queue */
64
static inline void sonypi_initq(void) {
65
        sonypi_device.queue.head = sonypi_device.queue.tail = 0;
66
        sonypi_device.queue.len = 0;
67
        sonypi_device.queue.s_lock = (spinlock_t)SPIN_LOCK_UNLOCKED;
68
        init_waitqueue_head(&sonypi_device.queue.proc_list);
69
}
70
 
71
/* Pulls an event from the queue */
72
static inline unsigned char sonypi_pullq(void) {
73
        unsigned char result;
74
        unsigned long flags;
75
 
76
        spin_lock_irqsave(&sonypi_device.queue.s_lock, flags);
77
        if (!sonypi_device.queue.len) {
78
                spin_unlock_irqrestore(&sonypi_device.queue.s_lock, flags);
79
                return 0;
80
        }
81
        result = sonypi_device.queue.buf[sonypi_device.queue.head];
82
        sonypi_device.queue.head++;
83
        sonypi_device.queue.head &= (SONYPI_BUF_SIZE - 1);
84
        sonypi_device.queue.len--;
85
        spin_unlock_irqrestore(&sonypi_device.queue.s_lock, flags);
86
        return result;
87
}
88
 
89
/* Pushes an event into the queue */
90
static inline void sonypi_pushq(unsigned char event) {
91
        unsigned long flags;
92
 
93
        spin_lock_irqsave(&sonypi_device.queue.s_lock, flags);
94
        if (sonypi_device.queue.len == SONYPI_BUF_SIZE) {
95
                /* remove the first element */
96
                sonypi_device.queue.head++;
97
                sonypi_device.queue.head &= (SONYPI_BUF_SIZE - 1);
98
                sonypi_device.queue.len--;
99
        }
100
        sonypi_device.queue.buf[sonypi_device.queue.tail] = event;
101
        sonypi_device.queue.tail++;
102
        sonypi_device.queue.tail &= (SONYPI_BUF_SIZE - 1);
103
        sonypi_device.queue.len++;
104
 
105
        kill_fasync(&sonypi_device.queue.fasync, SIGIO, POLL_IN);
106
        wake_up_interruptible(&sonypi_device.queue.proc_list);
107
        spin_unlock_irqrestore(&sonypi_device.queue.s_lock, flags);
108
}
109
 
110
/* Tests if the queue is empty */
111
static inline int sonypi_emptyq(void) {
112
        int result;
113
        unsigned long flags;
114
 
115
        spin_lock_irqsave(&sonypi_device.queue.s_lock, flags);
116
        result = (sonypi_device.queue.len == 0);
117
        spin_unlock_irqrestore(&sonypi_device.queue.s_lock, flags);
118
        return result;
119
}
120
 
121
static int ec_read16(u8 addr, u16 *value) {
122
        u8 val_lb, val_hb;
123
        if (sonypi_ec_read(addr, &val_lb))
124
                return -1;
125
        if (sonypi_ec_read(addr + 1, &val_hb))
126
                return -1;
127
        *value = val_lb | (val_hb << 8);
128
        return 0;
129
}
130
 
131
/* Initializes the device - this comes from the AML code in the ACPI bios */
132
static void sonypi_type1_srs(void) {
133
        u32 v;
134
 
135
        pci_read_config_dword(sonypi_device.dev, SONYPI_G10A, &v);
136
        v = (v & 0xFFFF0000) | ((u32)sonypi_device.ioport1);
137
        pci_write_config_dword(sonypi_device.dev, SONYPI_G10A, v);
138
 
139
        pci_read_config_dword(sonypi_device.dev, SONYPI_G10A, &v);
140
        v = (v & 0xFFF0FFFF) |
141
            (((u32)sonypi_device.ioport1 ^ sonypi_device.ioport2) << 16);
142
        pci_write_config_dword(sonypi_device.dev, SONYPI_G10A, v);
143
 
144
        v = inl(SONYPI_IRQ_PORT);
145
        v &= ~(((u32)0x3) << SONYPI_IRQ_SHIFT);
146
        v |= (((u32)sonypi_device.bits) << SONYPI_IRQ_SHIFT);
147
        outl(v, SONYPI_IRQ_PORT);
148
 
149
        pci_read_config_dword(sonypi_device.dev, SONYPI_G10A, &v);
150
        v = (v & 0xFF1FFFFF) | 0x00C00000;
151
        pci_write_config_dword(sonypi_device.dev, SONYPI_G10A, v);
152
}
153
 
154
static void sonypi_type2_srs(void) {
155
        if (sonypi_ec_write(SONYPI_SHIB, (sonypi_device.ioport1 & 0xFF00) >> 8))
156
                printk(KERN_WARNING "ec_write failed\n");
157
        if (sonypi_ec_write(SONYPI_SLOB,  sonypi_device.ioport1 & 0x00FF))
158
                printk(KERN_WARNING "ec_write failed\n");
159
        if (sonypi_ec_write(SONYPI_SIRQ,  sonypi_device.bits))
160
                printk(KERN_WARNING "ec_write failed\n");
161
        udelay(10);
162
}
163
 
164
/* Disables the device - this comes from the AML code in the ACPI bios */
165
static void sonypi_type1_dis(void) {
166
        u32 v;
167
 
168
        pci_read_config_dword(sonypi_device.dev, SONYPI_G10A, &v);
169
        v = v & 0xFF3FFFFF;
170
        pci_write_config_dword(sonypi_device.dev, SONYPI_G10A, v);
171
 
172
        v = inl(SONYPI_IRQ_PORT);
173
        v |= (0x3 << SONYPI_IRQ_SHIFT);
174
        outl(v, SONYPI_IRQ_PORT);
175
}
176
 
177
static void sonypi_type2_dis(void) {
178
        if (sonypi_ec_write(SONYPI_SHIB, 0))
179
                printk(KERN_WARNING "ec_write failed\n");
180
        if (sonypi_ec_write(SONYPI_SLOB, 0))
181
                printk(KERN_WARNING "ec_write failed\n");
182
        if (sonypi_ec_write(SONYPI_SIRQ, 0))
183
                printk(KERN_WARNING "ec_write failed\n");
184
}
185
 
186
static u8 sonypi_call1(u8 dev) {
187
        u8 v1, v2;
188
 
189
        wait_on_command(0, inb_p(sonypi_device.ioport2) & 2, ITERATIONS_LONG);
190
        outb(dev, sonypi_device.ioport2);
191
        v1 = inb_p(sonypi_device.ioport2);
192
        v2 = inb_p(sonypi_device.ioport1);
193
        return v2;
194
}
195
 
196
static u8 sonypi_call2(u8 dev, u8 fn) {
197
        u8 v1;
198
 
199
        wait_on_command(0, inb_p(sonypi_device.ioport2) & 2, ITERATIONS_LONG);
200
        outb(dev, sonypi_device.ioport2);
201
        wait_on_command(0, inb_p(sonypi_device.ioport2) & 2, ITERATIONS_LONG);
202
        outb(fn, sonypi_device.ioport1);
203
        v1 = inb_p(sonypi_device.ioport1);
204
        return v1;
205
}
206
 
207
static u8 sonypi_call3(u8 dev, u8 fn, u8 v) {
208
        u8 v1;
209
 
210
        wait_on_command(0, inb_p(sonypi_device.ioport2) & 2, ITERATIONS_LONG);
211
        outb(dev, sonypi_device.ioport2);
212
        wait_on_command(0, inb_p(sonypi_device.ioport2) & 2, ITERATIONS_LONG);
213
        outb(fn, sonypi_device.ioport1);
214
        wait_on_command(0, inb_p(sonypi_device.ioport2) & 2, ITERATIONS_LONG);
215
        outb(v, sonypi_device.ioport1);
216
        v1 = inb_p(sonypi_device.ioport1);
217
        return v1;
218
}
219
 
220
static u8 sonypi_read(u8 fn) {
221
        u8 v1, v2;
222
        int n = 100;
223
 
224
        while (n--) {
225
                v1 = sonypi_call2(0x8f, fn);
226
                v2 = sonypi_call2(0x8f, fn);
227
                if (v1 == v2 && v1 != 0xff)
228
                        return v1;
229
        }
230
        return 0xff;
231
}
232
 
233
/* Set brightness, hue etc */
234
static void sonypi_set(u8 fn, u8 v) {
235
 
236
        wait_on_command(0, sonypi_call3(0x90, fn, v), ITERATIONS_SHORT);
237
}
238
 
239
/* Tests if the camera is ready */
240
static int sonypi_camera_ready(void) {
241
        u8 v;
242
 
243
        v = sonypi_call2(0x8f, SONYPI_CAMERA_STATUS);
244
        return (v != 0xff && (v & SONYPI_CAMERA_STATUS_READY));
245
}
246
 
247
/* Turns the camera off */
248
static void sonypi_camera_off(void) {
249
 
250
        sonypi_set(SONYPI_CAMERA_PICTURE, SONYPI_CAMERA_MUTE_MASK);
251
 
252
        if (!sonypi_device.camera_power)
253
                return;
254
 
255
        sonypi_call2(0x91, 0);
256
        sonypi_device.camera_power = 0;
257
}
258
 
259
/* Turns the camera on */
260
static void sonypi_camera_on(void) {
261
        int i, j;
262
 
263
        if (sonypi_device.camera_power)
264
                return;
265
 
266
        for (j = 5; j > 0; j--) {
267
 
268
                while (sonypi_call2(0x91, 0x1)) {
269
                        set_current_state(TASK_UNINTERRUPTIBLE);
270
                        schedule_timeout(1);
271
                }
272
                sonypi_call1(0x93);
273
 
274
                for (i = 400; i > 0; i--) {
275
                        if (sonypi_camera_ready())
276
                                break;
277
                        set_current_state(TASK_UNINTERRUPTIBLE);
278
                        schedule_timeout(1);
279
                }
280
                if (i)
281
                        break;
282
        }
283
 
284
        if (j == 0) {
285
                printk(KERN_WARNING "sonypi: failed to power on camera\n");
286
                return;
287
        }
288
 
289
        sonypi_set(0x10, 0x5a);
290
        sonypi_device.camera_power = 1;
291
}
292
 
293
/* sets the bluetooth subsystem power state */
294
static void sonypi_setbluetoothpower(u8 state) {
295
 
296
        state = !!state;
297
        if (sonypi_device.bluetooth_power == state)
298
                return;
299
 
300
        sonypi_call2(0x96, state);
301
        sonypi_call1(0x82);
302
        sonypi_device.bluetooth_power = state;
303
}
304
 
305
/* Interrupt handler: some event is available */
306
static irqreturn_t sonypi_irq(int irq, void *dev_id, struct pt_regs *regs) {
307
        u8 v1, v2, event = 0;
308
        int i, j;
309
 
310
        v1 = inb_p(sonypi_device.ioport1);
311
        v2 = inb_p(sonypi_device.ioport1 + sonypi_device.evtype_offset);
312
 
313
        for (i = 0; sonypi_eventtypes[i].model; i++) {
314
                if (sonypi_device.model != sonypi_eventtypes[i].model)
315
                        continue;
316
                if ((v2 & sonypi_eventtypes[i].data) != sonypi_eventtypes[i].data)
317
                        continue;
318
                if (! (mask & sonypi_eventtypes[i].mask))
319
                        continue;
320
                for (j = 0; sonypi_eventtypes[i].events[j].event; j++) {
321
                        if (v1 == sonypi_eventtypes[i].events[j].data) {
322
                                event = sonypi_eventtypes[i].events[j].event;
323
                                goto found;
324
                        }
325
                }
326
        }
327
 
328
        if (verbose)
329
                printk(KERN_WARNING
330
                       "sonypi: unknown event port1=0x%02x,port2=0x%02x\n",v1,v2);
331
        /* We need to return IRQ_HANDLED here because there *are*
332
         * events belonging to the sonypi device we don't know about,
333
         * but we still don't want those to pollute the logs... */
334
        return IRQ_HANDLED;
335
 
336
found:
337
        if (verbose > 1)
338
                printk(KERN_INFO
339
                       "sonypi: event port1=0x%02x,port2=0x%02x\n", v1, v2);
340
 
341
#ifdef SONYPI_USE_INPUT
342
        if (useinput) {
343
                struct input_dev *jog_dev = &sonypi_device.jog_dev;
344
                if (event == SONYPI_EVENT_JOGDIAL_PRESSED)
345
                        input_report_key(jog_dev, BTN_MIDDLE, 1);
346
                else if (event == SONYPI_EVENT_ANYBUTTON_RELEASED)
347
                        input_report_key(jog_dev, BTN_MIDDLE, 0);
348
                else if ((event == SONYPI_EVENT_JOGDIAL_UP) ||
349
                         (event == SONYPI_EVENT_JOGDIAL_UP_PRESSED))
350
                        input_report_rel(jog_dev, REL_WHEEL, 1);
351
                else if ((event == SONYPI_EVENT_JOGDIAL_DOWN) ||
352
                         (event == SONYPI_EVENT_JOGDIAL_DOWN_PRESSED))
353
                        input_report_rel(jog_dev, REL_WHEEL, -1);
354
        }
355
#endif /* SONYPI_USE_INPUT */
356
        sonypi_pushq(event);
357
        return IRQ_HANDLED;
358
}
359
 
360
/* External camera command (exported to the motion eye v4l driver) */
361
u8 sonypi_camera_command(int command, u8 value) {
362
        u8 ret = 0;
363
 
364
        if (!camera)
365
                return 0;
366
 
367
        down(&sonypi_device.lock);
368
 
369
        switch(command) {
370
                case SONYPI_COMMAND_GETCAMERA:
371
                        ret = sonypi_camera_ready();
372
                        break;
373
                case SONYPI_COMMAND_SETCAMERA:
374
                        if (value)
375
                                sonypi_camera_on();
376
                        else
377
                                sonypi_camera_off();
378
                        break;
379
                case SONYPI_COMMAND_GETCAMERABRIGHTNESS:
380
                        ret = sonypi_read(SONYPI_CAMERA_BRIGHTNESS);
381
                        break;
382
                case SONYPI_COMMAND_SETCAMERABRIGHTNESS:
383
                        sonypi_set(SONYPI_CAMERA_BRIGHTNESS, value);
384
                        break;
385
                case SONYPI_COMMAND_GETCAMERACONTRAST:
386
                        ret = sonypi_read(SONYPI_CAMERA_CONTRAST);
387
                        break;
388
                case SONYPI_COMMAND_SETCAMERACONTRAST:
389
                        sonypi_set(SONYPI_CAMERA_CONTRAST, value);
390
                        break;
391
                case SONYPI_COMMAND_GETCAMERAHUE:
392
                        ret = sonypi_read(SONYPI_CAMERA_HUE);
393
                        break;
394
                case SONYPI_COMMAND_SETCAMERAHUE:
395
                        sonypi_set(SONYPI_CAMERA_HUE, value);
396
                        break;
397
                case SONYPI_COMMAND_GETCAMERACOLOR:
398
                        ret = sonypi_read(SONYPI_CAMERA_COLOR);
399
                        break;
400
                case SONYPI_COMMAND_SETCAMERACOLOR:
401
                        sonypi_set(SONYPI_CAMERA_COLOR, value);
402
                        break;
403
                case SONYPI_COMMAND_GETCAMERASHARPNESS:
404
                        ret = sonypi_read(SONYPI_CAMERA_SHARPNESS);
405
                        break;
406
                case SONYPI_COMMAND_SETCAMERASHARPNESS:
407
                        sonypi_set(SONYPI_CAMERA_SHARPNESS, value);
408
                        break;
409
                case SONYPI_COMMAND_GETCAMERAPICTURE:
410
                        ret = sonypi_read(SONYPI_CAMERA_PICTURE);
411
                        break;
412
                case SONYPI_COMMAND_SETCAMERAPICTURE:
413
                        sonypi_set(SONYPI_CAMERA_PICTURE, value);
414
                        break;
415
                case SONYPI_COMMAND_GETCAMERAAGC:
416
                        ret = sonypi_read(SONYPI_CAMERA_AGC);
417
                        break;
418
                case SONYPI_COMMAND_SETCAMERAAGC:
419
                        sonypi_set(SONYPI_CAMERA_AGC, value);
420
                        break;
421
                case SONYPI_COMMAND_GETCAMERADIRECTION:
422
                        ret = sonypi_read(SONYPI_CAMERA_STATUS);
423
                        ret &= SONYPI_DIRECTION_BACKWARDS;
424
                        break;
425
                case SONYPI_COMMAND_GETCAMERAROMVERSION:
426
                        ret = sonypi_read(SONYPI_CAMERA_ROMVERSION);
427
                        break;
428
                case SONYPI_COMMAND_GETCAMERAREVISION:
429
                        ret = sonypi_read(SONYPI_CAMERA_REVISION);
430
                        break;
431
        }
432
        up(&sonypi_device.lock);
433
        return ret;
434
}
435
 
436
static int sonypi_misc_fasync(int fd, struct file *filp, int on) {
437
        int retval;
438
 
439
        retval = fasync_helper(fd, filp, on, &sonypi_device.queue.fasync);
440
        if (retval < 0)
441
                return retval;
442
        return 0;
443
}
444
 
445
static int sonypi_misc_release(struct inode * inode, struct file * file) {
446
        sonypi_misc_fasync(-1, file, 0);
447
        down(&sonypi_device.lock);
448
        sonypi_device.open_count--;
449
        up(&sonypi_device.lock);
450
        return 0;
451
}
452
 
453
static int sonypi_misc_open(struct inode * inode, struct file * file) {
454
        down(&sonypi_device.lock);
455
        /* Flush input queue on first open */
456
        if (!sonypi_device.open_count)
457
                sonypi_initq();
458
        sonypi_device.open_count++;
459
        up(&sonypi_device.lock);
460
        return 0;
461
}
462
 
463
static ssize_t sonypi_misc_read(struct file * file, char * buf,
464
                                size_t count, loff_t *pos) {
465
        DECLARE_WAITQUEUE(wait, current);
466
        ssize_t i = count;
467
        unsigned char c;
468
 
469
        if (sonypi_emptyq()) {
470
                if (file->f_flags & O_NONBLOCK)
471
                        return -EAGAIN;
472
                add_wait_queue(&sonypi_device.queue.proc_list, &wait);
473
repeat:
474
                set_current_state(TASK_INTERRUPTIBLE);
475
                if (sonypi_emptyq() && !signal_pending(current)) {
476
                        schedule();
477
                        goto repeat;
478
                }
479
                current->state = TASK_RUNNING;
480
                remove_wait_queue(&sonypi_device.queue.proc_list, &wait);
481
        }
482
        while (i > 0 && !sonypi_emptyq()) {
483
                c = sonypi_pullq();
484
                put_user(c, buf++);
485
                i--;
486
        }
487
        if (count - i) {
488
                file->f_dentry->d_inode->i_atime = CURRENT_TIME;
489
                return count-i;
490
        }
491
        if (signal_pending(current))
492
                return -ERESTARTSYS;
493
        return 0;
494
}
495
 
496
static unsigned int sonypi_misc_poll(struct file *file, poll_table * wait) {
497
        poll_wait(file, &sonypi_device.queue.proc_list, wait);
498
        if (!sonypi_emptyq())
499
                return POLLIN | POLLRDNORM;
500
        return 0;
501
}
502
 
503
static int sonypi_misc_ioctl(struct inode *ip, struct file *fp,
504
                             unsigned int cmd, unsigned long arg) {
505
        int ret = 0;
506
        u8 val8;
507
        u16 val16;
508
 
509
        down(&sonypi_device.lock);
510
        switch (cmd) {
511
        case SONYPI_IOCGBRT:
512
                if (sonypi_ec_read(SONYPI_LCD_LIGHT, &val8)) {
513
                        ret = -EIO;
514
                        break;
515
                }
516
                if (copy_to_user((u8 *)arg, &val8, sizeof(val8)))
517
                        ret = -EFAULT;
518
                break;
519
        case SONYPI_IOCSBRT:
520
                if (copy_from_user(&val8, (u8 *)arg, sizeof(val8))) {
521
                        ret = -EFAULT;
522
                        break;
523
                }
524
                if (sonypi_ec_write(SONYPI_LCD_LIGHT, val8))
525
                        ret = -EIO;
526
                break;
527
        case SONYPI_IOCGBAT1CAP:
528
                if (ec_read16(SONYPI_BAT1_FULL, &val16)) {
529
                        ret = -EIO;
530
                        break;
531
                }
532
                if (copy_to_user((u16 *)arg, &val16, sizeof(val16)))
533
                        ret = -EFAULT;
534
                break;
535
        case SONYPI_IOCGBAT1REM:
536
                if (ec_read16(SONYPI_BAT1_LEFT, &val16)) {
537
                        ret = -EIO;
538
                        break;
539
                }
540
                if (copy_to_user((u16 *)arg, &val16, sizeof(val16)))
541
                        ret = -EFAULT;
542
                break;
543
        case SONYPI_IOCGBAT2CAP:
544
                if (ec_read16(SONYPI_BAT2_FULL, &val16)) {
545
                        ret = -EIO;
546
                        break;
547
                }
548
                if (copy_to_user((u16 *)arg, &val16, sizeof(val16)))
549
                        ret = -EFAULT;
550
                break;
551
        case SONYPI_IOCGBAT2REM:
552
                if (ec_read16(SONYPI_BAT2_LEFT, &val16)) {
553
                        ret = -EIO;
554
                        break;
555
                }
556
                if (copy_to_user((u16 *)arg, &val16, sizeof(val16)))
557
                        ret = -EFAULT;
558
                break;
559
        case SONYPI_IOCGBATFLAGS:
560
                if (sonypi_ec_read(SONYPI_BAT_FLAGS, &val8)) {
561
                        ret = -EIO;
562
                        break;
563
                }
564
                val8 &= 0x07;
565
                if (copy_to_user((u8 *)arg, &val8, sizeof(val8)))
566
                        ret = -EFAULT;
567
                break;
568
        case SONYPI_IOCGBLUE:
569
                val8 = sonypi_device.bluetooth_power;
570
                if (copy_to_user((u8 *)arg, &val8, sizeof(val8)))
571
                        ret = -EFAULT;
572
                break;
573
        case SONYPI_IOCSBLUE:
574
                if (copy_from_user(&val8, (u8 *)arg, sizeof(val8))) {
575
                        ret = -EFAULT;
576
                        break;
577
                }
578
                sonypi_setbluetoothpower(val8);
579
                break;
580
        default:
581
                ret = -EINVAL;
582
        }
583
        up(&sonypi_device.lock);
584
        return ret;
585
}
586
 
587
static struct file_operations sonypi_misc_fops = {
588
        .owner          = THIS_MODULE,
589
        .read           = sonypi_misc_read,
590
        .poll           = sonypi_misc_poll,
591
        .open           = sonypi_misc_open,
592
        .release        = sonypi_misc_release,
593
        .fasync         = sonypi_misc_fasync,
594
        .ioctl          = sonypi_misc_ioctl,
595
};
596
 
597
struct miscdevice sonypi_misc_device = {
598
        -1, "sonypi", &sonypi_misc_fops
599
};
600
 
601
#ifdef CONFIG_PM
602
static int sonypi_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) {
603
        static int old_camera_power;
604
 
605
        switch (rqst) {
606
        case PM_SUSPEND:
607
                sonypi_call2(0x81, 0); /* make sure we don't get any more events */
608
                if (camera) {
609
                        old_camera_power = sonypi_device.camera_power;
610
                        sonypi_camera_off();
611
                }
612
                if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
613
                        sonypi_type2_dis();
614
                else
615
                        sonypi_type1_dis();
616
                /* disable ACPI mode */
617
                if (!SONYPI_ACPI_ACTIVE && fnkeyinit)
618
                        outb(0xf1, 0xb2);
619
                break;
620
        case PM_RESUME:
621
                /* Enable ACPI mode to get Fn key events */
622
                if (!SONYPI_ACPI_ACTIVE && fnkeyinit)
623
                        outb(0xf0, 0xb2);
624
                if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
625
                        sonypi_type2_srs();
626
                else
627
                        sonypi_type1_srs();
628
                sonypi_call1(0x82);
629
                sonypi_call2(0x81, 0xff);
630
                if (compat)
631
                        sonypi_call1(0x92);
632
                else
633
                        sonypi_call1(0x82);
634
                if (camera && old_camera_power)
635
                        sonypi_camera_on();
636
                break;
637
        }
638
        return 0;
639
}
640
#endif
641
 
642
static int __devinit sonypi_probe(struct pci_dev *pcidev) {
643
        int i, ret;
644
        struct sonypi_ioport_list *ioport_list;
645
        struct sonypi_irq_list *irq_list;
646
 
647
        sonypi_device.dev = pcidev;
648
        if (pcidev)
649
                sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE1;
650
        else
651
                sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2;
652
        sonypi_initq();
653
        init_MUTEX(&sonypi_device.lock);
654
        sonypi_device.bluetooth_power = 0;
655
 
656
        if (pcidev && pci_enable_device(pcidev)) {
657
                printk(KERN_ERR "sonypi: pci_enable_device failed\n");
658
                ret = -EIO;
659
                goto out1;
660
        }
661
 
662
        sonypi_misc_device.minor = (minor == -1) ?
663
                MISC_DYNAMIC_MINOR : minor;
664
        if ((ret = misc_register(&sonypi_misc_device))) {
665
                printk(KERN_ERR "sonypi: misc_register failed\n");
666
                goto out1;
667
        }
668
 
669
        if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) {
670
                ioport_list = sonypi_type2_ioport_list;
671
                sonypi_device.region_size = SONYPI_TYPE2_REGION_SIZE;
672
                sonypi_device.evtype_offset = SONYPI_TYPE2_EVTYPE_OFFSET;
673
                irq_list = sonypi_type2_irq_list;
674
        }
675
        else {
676
                ioport_list = sonypi_type1_ioport_list;
677
                sonypi_device.region_size = SONYPI_TYPE1_REGION_SIZE;
678
                sonypi_device.evtype_offset = SONYPI_TYPE1_EVTYPE_OFFSET;
679
                irq_list = sonypi_type1_irq_list;
680
        }
681
 
682
        for (i = 0; ioport_list[i].port1; i++) {
683
                if (request_region(ioport_list[i].port1,
684
                                   sonypi_device.region_size,
685
                                   "Sony Programable I/O Device")) {
686
                        /* get the ioport */
687
                        sonypi_device.ioport1 = ioport_list[i].port1;
688
                        sonypi_device.ioport2 = ioport_list[i].port2;
689
                        break;
690
                }
691
        }
692
        if (!sonypi_device.ioport1) {
693
                printk(KERN_ERR "sonypi: request_region failed\n");
694
                ret = -ENODEV;
695
                goto out2;
696
        }
697
 
698
        for (i = 0; irq_list[i].irq; i++) {
699
 
700
                sonypi_device.irq = irq_list[i].irq;
701
                sonypi_device.bits = irq_list[i].bits;
702
 
703
                /* Enable sonypi IRQ settings */
704
                if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
705
                        sonypi_type2_srs();
706
                else
707
                        sonypi_type1_srs();
708
 
709
                sonypi_call1(0x82);
710
                sonypi_call2(0x81, 0xff);
711
                if (compat)
712
                        sonypi_call1(0x92);
713
                else
714
                        sonypi_call1(0x82);
715
 
716
                /* Now try requesting the irq from the system */
717
                if (!request_irq(sonypi_device.irq, sonypi_irq,
718
                                 SA_SHIRQ, "sonypi", sonypi_irq))
719
                        break;
720
 
721
                /* If request_irq failed, disable sonypi IRQ settings */
722
                if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
723
                        sonypi_type2_dis();
724
                else
725
                        sonypi_type1_dis();
726
        }
727
 
728
        if (!irq_list[i].irq) {
729
                printk(KERN_ERR "sonypi: request_irq failed\n");
730
                ret = -ENODEV;
731
                goto out3;
732
        }
733
 
734
        /* Enable ACPI mode to get Fn key events */
735
        if (!SONYPI_ACPI_ACTIVE && fnkeyinit)
736
                outb(0xf0, 0xb2);
737
 
738
        printk(KERN_INFO "sonypi: Sony Programmable I/O Controller Driver v%d.%d.\n",
739
               SONYPI_DRIVER_MAJORVERSION,
740
               SONYPI_DRIVER_MINORVERSION);
741
        printk(KERN_INFO "sonypi: detected %s model, "
742
               "verbose = %d, fnkeyinit = %s, camera = %s, "
743
               "compat = %s, mask = 0x%08lx, useinput = %s\n",
744
               (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) ?
745
                        "type1" : "type2",
746
               verbose,
747
               fnkeyinit ? "on" : "off",
748
               camera ? "on" : "off",
749
               compat ? "on" : "off",
750
               mask,
751
               useinput ? "on" : "off");
752
        printk(KERN_INFO "sonypi: enabled at irq=%d, port1=0x%x, port2=0x%x\n",
753
               sonypi_device.irq,
754
               sonypi_device.ioport1, sonypi_device.ioport2);
755
        if (minor == -1)
756
                printk(KERN_INFO "sonypi: device allocated minor is %d\n",
757
                       sonypi_misc_device.minor);
758
 
759
#ifdef SONYPI_USE_INPUT
760
        if (useinput) {
761
                /* Initialize the Input Drivers: */
762
                sonypi_device.jog_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
763
                sonypi_device.jog_dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_MIDDLE);
764
                sonypi_device.jog_dev.relbit[0] = BIT(REL_WHEEL);
765
                sonypi_device.jog_dev.name = (char *) kmalloc(
766
                        sizeof(SONYPI_INPUTNAME), GFP_KERNEL);
767
                sprintf(sonypi_device.jog_dev.name, SONYPI_INPUTNAME);
768
                sonypi_device.jog_dev.idbus = BUS_ISA;
769
                sonypi_device.jog_dev.idvendor = PCI_VENDOR_ID_SONY;
770
 
771
                input_register_device(&sonypi_device.jog_dev);
772
                printk(KERN_INFO "%s installed at input event device #%d.\n",
773
                        sonypi_device.jog_dev.name,
774
                        sonypi_device.jog_dev.number);
775
        }
776
#endif /* SONYPI_USE_INPUT */
777
 
778
#ifdef CONFIG_PM
779
        sonypi_device.pm = pm_register(PM_PCI_DEV, 0, sonypi_pm_callback);
780
#endif
781
 
782
        return 0;
783
 
784
out3:
785
        release_region(sonypi_device.ioport1, sonypi_device.region_size);
786
out2:
787
        misc_deregister(&sonypi_misc_device);
788
out1:
789
        return ret;
790
}
791
 
792
static void __devexit sonypi_remove(void) {
793
 
794
#ifdef CONFIG_PM
795
        pm_unregister(sonypi_device.pm);
796
#endif
797
 
798
        sonypi_call2(0x81, 0); /* make sure we don't get any more events */
799
 
800
#ifdef SONYPI_USE_INPUT
801
        if (useinput) {
802
                input_unregister_device(&sonypi_device.jog_dev);
803
                kfree(sonypi_device.jog_dev.name);
804
        }
805
#endif /* SONYPI_USE_INPUT */
806
 
807
        if (camera)
808
                sonypi_camera_off();
809
        if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
810
                sonypi_type2_dis();
811
        else
812
                sonypi_type1_dis();
813
        /* disable ACPI mode */
814
        if (!SONYPI_ACPI_ACTIVE && fnkeyinit)
815
                outb(0xf1, 0xb2);
816
        free_irq(sonypi_device.irq, sonypi_irq);
817
        release_region(sonypi_device.ioport1, sonypi_device.region_size);
818
        misc_deregister(&sonypi_misc_device);
819
        printk(KERN_INFO "sonypi: removed.\n");
820
}
821
 
822
static int __init sonypi_init_module(void) {
823
        struct pci_dev *pcidev = NULL;
824
 
825
        if (is_sony_vaio_laptop) {
826
                pcidev = pci_find_device(PCI_VENDOR_ID_INTEL,
827
                                         PCI_DEVICE_ID_INTEL_82371AB_3,
828
                                         NULL);
829
                return sonypi_probe(pcidev);
830
        }
831
        else
832
                return -ENODEV;
833
}
834
 
835
static void __exit sonypi_cleanup_module(void) {
836
        sonypi_remove();
837
}
838
 
839
#ifndef MODULE
840
static int __init sonypi_setup(char *str)  {
841
        int ints[8];
842
 
843
        str = get_options(str, ARRAY_SIZE(ints), ints);
844
        if (ints[0] <= 0)
845
                goto out;
846
        minor = ints[1];
847
        if (ints[0] == 1)
848
                goto out;
849
        verbose = ints[2];
850
        if (ints[0] == 2)
851
                goto out;
852
        fnkeyinit = ints[3];
853
        if (ints[0] == 3)
854
                goto out;
855
        camera = ints[4];
856
        if (ints[0] == 4)
857
                goto out;
858
        compat = ints[5];
859
        if (ints[0] == 5)
860
                goto out;
861
        mask = ints[6];
862
        if (ints[0] == 6)
863
                goto out;
864
        useinput = ints[7];
865
out:
866
        return 1;
867
}
868
 
869
__setup("sonypi=", sonypi_setup);
870
#endif /* !MODULE */
871
 
872
/* Module entry points */
873
module_init(sonypi_init_module);
874
module_exit(sonypi_cleanup_module);
875
 
876
MODULE_AUTHOR("Stelian Pop <stelian@popies.net>");
877
MODULE_DESCRIPTION("Sony Programmable I/O Control Device driver");
878
MODULE_LICENSE("GPL");
879
 
880
 
881
MODULE_PARM(minor,"i");
882
MODULE_PARM_DESC(minor, "minor number of the misc device, default is -1 (automatic)");
883
MODULE_PARM(verbose,"i");
884
MODULE_PARM_DESC(verbose, "be verbose, default is 0 (no)");
885
MODULE_PARM(fnkeyinit,"i");
886
MODULE_PARM_DESC(fnkeyinit, "set this if your Fn keys do not generate any event");
887
MODULE_PARM(camera,"i");
888
MODULE_PARM_DESC(camera, "set this if you have a MotionEye camera (PictureBook series)");
889
MODULE_PARM(compat,"i");
890
MODULE_PARM_DESC(compat, "set this if you want to enable backward compatibility mode");
891
MODULE_PARM(mask, "i");
892
MODULE_PARM_DESC(mask, "set this to the mask of event you want to enable (see doc)");
893
MODULE_PARM(useinput, "i");
894
MODULE_PARM_DESC(useinput, "if you have a jogdial, set this if you would like it to use the modern Linux Input Driver system");
895
 
896
EXPORT_SYMBOL(sonypi_camera_command);

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.