sonypi.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:21k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* 
  2.  * Sony Programmable I/O Control Device driver for VAIO
  3.  *
  4.  * Copyright (C) 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alc魐e
  5.  *
  6.  * Copyright (C) 2001 Michael Ashley <m.ashley@unsw.edu.au>
  7.  *
  8.  * Copyright (C) 2001 Junichi Morita <jun1m@mars.dti.ne.jp>
  9.  *
  10.  * Copyright (C) 2000 Takaya Kinjo <t-kinjo@tc4.so-net.ne.jp>
  11.  *
  12.  * Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com>
  13.  *
  14.  * Earlier work by Werner Almesberger, Paul `Rusty' Russell and Paul Mackerras.
  15.  *
  16.  * This program is free software; you can redistribute it and/or modify
  17.  * it under the terms of the GNU General Public License as published by
  18.  * the Free Software Foundation; either version 2 of the License, or
  19.  * (at your option) any later version.
  20.  * 
  21.  * This program is distributed in the hope that it will be useful,
  22.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24.  * GNU General Public License for more details.
  25.  * 
  26.  * You should have received a copy of the GNU General Public License
  27.  * along with this program; if not, write to the Free Software
  28.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  29.  *
  30.  */
  31. #include <linux/config.h>
  32. #include <linux/module.h>
  33. #include <linux/pci.h>
  34. #include <linux/sched.h>
  35. #include <linux/init.h>
  36. #include <linux/miscdevice.h>
  37. #include <linux/poll.h>
  38. #include <linux/delay.h>
  39. #include <asm/uaccess.h>
  40. #include <asm/io.h>
  41. #include <asm/system.h>
  42. #include "sonypi.h"
  43. #include <linux/sonypi.h>
  44. static struct sonypi_device sonypi_device;
  45. static int minor = -1;
  46. static int verbose; /* = 0 */
  47. static int fnkeyinit; /* = 0 */
  48. static int camera; /* = 0 */
  49. static int compat; /* = 0 */
  50. /* Inits the queue */
  51. static inline void sonypi_initq(void) {
  52.         sonypi_device.queue.head = sonypi_device.queue.tail = 0;
  53. sonypi_device.queue.len = 0;
  54. sonypi_device.queue.s_lock = (spinlock_t)SPIN_LOCK_UNLOCKED;
  55. init_waitqueue_head(&sonypi_device.queue.proc_list);
  56. }
  57. /* Pulls an event from the queue */
  58. static inline unsigned char sonypi_pullq(void) {
  59.         unsigned char result;
  60. unsigned long flags;
  61. spin_lock_irqsave(&sonypi_device.queue.s_lock, flags);
  62. if (!sonypi_device.queue.len) {
  63. spin_unlock_irqrestore(&sonypi_device.queue.s_lock, flags);
  64. return 0;
  65. }
  66. result = sonypi_device.queue.buf[sonypi_device.queue.head];
  67.         sonypi_device.queue.head++;
  68. sonypi_device.queue.head &= (SONYPI_BUF_SIZE - 1);
  69. sonypi_device.queue.len--;
  70. spin_unlock_irqrestore(&sonypi_device.queue.s_lock, flags);
  71.         return result;
  72. }
  73. /* Pushes an event into the queue */
  74. static inline void sonypi_pushq(unsigned char event) {
  75. unsigned long flags;
  76. spin_lock_irqsave(&sonypi_device.queue.s_lock, flags);
  77. if (sonypi_device.queue.len == SONYPI_BUF_SIZE) {
  78. /* remove the first element */
  79.          sonypi_device.queue.head++;
  80. sonypi_device.queue.head &= (SONYPI_BUF_SIZE - 1);
  81. sonypi_device.queue.len--;
  82. }
  83. sonypi_device.queue.buf[sonypi_device.queue.tail] = event;
  84. sonypi_device.queue.tail++;
  85. sonypi_device.queue.tail &= (SONYPI_BUF_SIZE - 1);
  86. sonypi_device.queue.len++;
  87. kill_fasync(&sonypi_device.queue.fasync, SIGIO, POLL_IN);
  88. wake_up_interruptible(&sonypi_device.queue.proc_list);
  89. spin_unlock_irqrestore(&sonypi_device.queue.s_lock, flags);
  90. }
  91. /* Tests if the queue is empty */
  92. static inline int sonypi_emptyq(void) {
  93.         int result;
  94. unsigned long flags;
  95. spin_lock_irqsave(&sonypi_device.queue.s_lock, flags);
  96.         result = (sonypi_device.queue.len == 0);
  97. spin_unlock_irqrestore(&sonypi_device.queue.s_lock, flags);
  98.         return result;
  99. }
  100. static void sonypi_ecrset(u8 addr, u8 value) {
  101. wait_on_command(1, inb_p(SONYPI_CST_IOPORT) & 3);
  102. outb_p(0x81, SONYPI_CST_IOPORT);
  103. wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2);
  104. outb_p(addr, SONYPI_DATA_IOPORT);
  105. wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2);
  106. outb_p(value, SONYPI_DATA_IOPORT);
  107. wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2);
  108. }
  109. static u8 sonypi_ecrget(u8 addr) {
  110. wait_on_command(1, inb_p(SONYPI_CST_IOPORT) & 3);
  111. outb_p(0x80, SONYPI_CST_IOPORT);
  112. wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2);
  113. outb_p(addr, SONYPI_DATA_IOPORT);
  114. wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2);
  115. return inb_p(SONYPI_DATA_IOPORT);
  116. }
  117. static u16 sonypi_ecrget16(u8 addr) {
  118. return sonypi_ecrget(addr) | (sonypi_ecrget(addr + 1) << 8);
  119. }
  120. /* Initializes the device - this comes from the AML code in the ACPI bios */
  121. static void __devinit sonypi_type1_srs(void) {
  122. u32 v;
  123. pci_read_config_dword(sonypi_device.dev, SONYPI_G10A, &v);
  124. v = (v & 0xFFFF0000) | ((u32)sonypi_device.ioport1);
  125. pci_write_config_dword(sonypi_device.dev, SONYPI_G10A, v);
  126. pci_read_config_dword(sonypi_device.dev, SONYPI_G10A, &v);
  127. v = (v & 0xFFF0FFFF) | 
  128.     (((u32)sonypi_device.ioport1 ^ sonypi_device.ioport2) << 16);
  129. pci_write_config_dword(sonypi_device.dev, SONYPI_G10A, v);
  130. v = inl(SONYPI_IRQ_PORT);
  131. v &= ~(((u32)0x3) << SONYPI_IRQ_SHIFT);
  132. v |= (((u32)sonypi_device.bits) << SONYPI_IRQ_SHIFT);
  133. outl(v, SONYPI_IRQ_PORT);
  134. pci_read_config_dword(sonypi_device.dev, SONYPI_G10A, &v);
  135. v = (v & 0xFF1FFFFF) | 0x00C00000;
  136. pci_write_config_dword(sonypi_device.dev, SONYPI_G10A, v);
  137. }
  138. static void __devinit sonypi_type2_srs(void) {
  139. sonypi_ecrset(SONYPI_SHIB, (sonypi_device.ioport1 & 0xFF00) >> 8);
  140. sonypi_ecrset(SONYPI_SLOB,  sonypi_device.ioport1 & 0x00FF);
  141. sonypi_ecrset(SONYPI_SIRQ,  sonypi_device.bits);
  142. udelay(10);
  143. }
  144. /* Disables the device - this comes from the AML code in the ACPI bios */
  145. static void __devexit sonypi_type1_dis(void) {
  146. u32 v;
  147. pci_read_config_dword(sonypi_device.dev, SONYPI_G10A, &v);
  148. v = v & 0xFF3FFFFF;
  149. pci_write_config_dword(sonypi_device.dev, SONYPI_G10A, v);
  150. v = inl(SONYPI_IRQ_PORT);
  151. v |= (0x3 << SONYPI_IRQ_SHIFT);
  152. outl(v, SONYPI_IRQ_PORT);
  153. }
  154. static void __devexit sonypi_type2_dis(void) {
  155. sonypi_ecrset(SONYPI_SHIB, 0);
  156. sonypi_ecrset(SONYPI_SLOB, 0);
  157. sonypi_ecrset(SONYPI_SIRQ, 0);
  158. }
  159. static u8 sonypi_call1(u8 dev) {
  160. u8 v1, v2;
  161. wait_on_command(0, inb_p(sonypi_device.ioport2) & 2);
  162. outb(dev, sonypi_device.ioport2);
  163. v1 = inb_p(sonypi_device.ioport2);
  164. v2 = inb_p(sonypi_device.ioport1);
  165. return v2;
  166. }
  167. static u8 sonypi_call2(u8 dev, u8 fn) {
  168. u8 v1;
  169. wait_on_command(0, inb_p(sonypi_device.ioport2) & 2);
  170. outb(dev, sonypi_device.ioport2);
  171. wait_on_command(0, inb_p(sonypi_device.ioport2) & 2);
  172. outb(fn, sonypi_device.ioport1);
  173. v1 = inb_p(sonypi_device.ioport1);
  174. return v1;
  175. }
  176. static u8 sonypi_call3(u8 dev, u8 fn, u8 v) {
  177. u8 v1;
  178. wait_on_command(0, inb_p(sonypi_device.ioport2) & 2);
  179. outb(dev, sonypi_device.ioport2);
  180. wait_on_command(0, inb_p(sonypi_device.ioport2) & 2);
  181. outb(fn, sonypi_device.ioport1);
  182. wait_on_command(0, inb_p(sonypi_device.ioport2) & 2);
  183. outb(v, sonypi_device.ioport1);
  184. v1 = inb_p(sonypi_device.ioport1);
  185. return v1;
  186. }
  187. static u8 sonypi_read(u8 fn) {
  188. u8 v1, v2;
  189. int n = 100;
  190. while (n--) {
  191. v1 = sonypi_call2(0x8f, fn);
  192. v2 = sonypi_call2(0x8f, fn);
  193. if (v1 == v2 && v1 != 0xff)
  194. return v1;
  195. }
  196. return 0xff;
  197. }
  198. /* Set brightness, hue etc */
  199. static void sonypi_set(u8 fn, u8 v) {
  200. wait_on_command(0, sonypi_call3(0x90, fn, v));
  201. }
  202. /* Tests if the camera is ready */
  203. static int sonypi_camera_ready(void) {
  204. u8 v;
  205. v = sonypi_call2(0x8f, SONYPI_CAMERA_STATUS);
  206. return (v != 0xff && (v & SONYPI_CAMERA_STATUS_READY));
  207. }
  208. /* Turns the camera off */
  209. static void sonypi_camera_off(void) {
  210. sonypi_set(SONYPI_CAMERA_PICTURE, SONYPI_CAMERA_MUTE_MASK);
  211. if (!sonypi_device.camera_power)
  212. return;
  213. sonypi_call2(0x91, 0); 
  214. sonypi_device.camera_power = 0;
  215. }
  216. /* Turns the camera on */
  217. static void sonypi_camera_on(void) {
  218. int i, j;
  219. if (sonypi_device.camera_power)
  220. return;
  221. for (j = 5; j > 0; j--) {
  222. while (sonypi_call2(0x91, 0x1) != 0) {
  223. set_current_state(TASK_UNINTERRUPTIBLE);
  224. schedule_timeout(1);
  225. }
  226. sonypi_call1(0x93);
  227. for (i = 400; i > 0; i--) {
  228. if (sonypi_camera_ready())
  229. break;
  230. set_current_state(TASK_UNINTERRUPTIBLE);
  231. schedule_timeout(1);
  232. }
  233. if (i != 0)
  234. break;
  235. }
  236. if (j == 0) {
  237. printk(KERN_WARNING "sonypi: failed to power on cameran");
  238. return;
  239. }
  240. sonypi_set(0x10, 0x5a);
  241. sonypi_device.camera_power = 1;
  242. }
  243. /* sets the bluetooth subsystem power state */
  244. static void sonypi_setbluetoothpower(u8 state) {
  245. state = (state != 0);
  246. if (sonypi_device.bluetooth_power && state) 
  247. return;
  248. if (!sonypi_device.bluetooth_power && !state) 
  249. return;
  250. sonypi_call2(0x96, state);
  251. sonypi_call1(0x93);
  252. sonypi_device.bluetooth_power = state;
  253. }
  254. /* Interrupt handler: some event is available */
  255. void sonypi_irq(int irq, void *dev_id, struct pt_regs *regs) {
  256. u8 v1, v2, event = 0;
  257. int i;
  258. u8 sonypi_jogger_ev, sonypi_fnkey_ev;
  259. u8 sonypi_capture_ev, sonypi_bluetooth_ev;
  260. if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) {
  261. sonypi_jogger_ev = SONYPI_TYPE2_JOGGER_EV;
  262. sonypi_fnkey_ev = SONYPI_TYPE2_FNKEY_EV;
  263. sonypi_capture_ev = SONYPI_TYPE2_CAPTURE_EV;
  264. sonypi_bluetooth_ev = SONYPI_TYPE2_BLUETOOTH_EV;
  265. }
  266. else {
  267. sonypi_jogger_ev = SONYPI_TYPE1_JOGGER_EV;
  268. sonypi_fnkey_ev = SONYPI_TYPE1_FNKEY_EV;
  269. sonypi_capture_ev = SONYPI_TYPE1_CAPTURE_EV;
  270. sonypi_bluetooth_ev = SONYPI_TYPE1_BLUETOOTH_EV;
  271. }
  272. v1 = inb_p(sonypi_device.ioport1);
  273. v2 = inb_p(sonypi_device.ioport2);
  274. if ((v2 & SONYPI_TYPE1_PKEY_EV) == SONYPI_TYPE1_PKEY_EV) {
  275. for (i = 0; sonypi_pkeyev[i].event; i++)
  276. if (sonypi_pkeyev[i].data == v1) {
  277. event = sonypi_pkeyev[i].event;
  278. goto found;
  279. }
  280. }
  281. if ((v2 & sonypi_jogger_ev) == sonypi_jogger_ev) {
  282. for (i = 0; sonypi_joggerev[i].event; i++)
  283. if (sonypi_joggerev[i].data == v1) {
  284. event = sonypi_joggerev[i].event;
  285. goto found;
  286. }
  287. }
  288. if ((v2 & sonypi_capture_ev) == sonypi_capture_ev) {
  289. for (i = 0; sonypi_captureev[i].event; i++)
  290. if (sonypi_captureev[i].data == v1) {
  291. event = sonypi_captureev[i].event;
  292. goto found;
  293. }
  294. }
  295. if ((v2 & sonypi_fnkey_ev) == sonypi_fnkey_ev) {
  296. for (i = 0; sonypi_fnkeyev[i].event; i++)
  297. if (sonypi_fnkeyev[i].data == v1) {
  298. event = sonypi_fnkeyev[i].event;
  299. goto found;
  300. }
  301. }
  302. if ((v2 & sonypi_bluetooth_ev) == sonypi_bluetooth_ev) {
  303. for (i = 0; sonypi_blueev[i].event; i++)
  304. if (sonypi_blueev[i].data == v1) {
  305. event = sonypi_blueev[i].event;
  306. goto found;
  307. }
  308. }
  309. if ((v2 & SONYPI_BACK_EV) == SONYPI_BACK_EV) {
  310. for (i = 0; sonypi_backev[i].event; i++)
  311. if (sonypi_backev[i].data == v1) {
  312. event = sonypi_backev[i].event;
  313. goto found;
  314. }
  315. }
  316. if ((v2 & SONYPI_LID_EV) == SONYPI_LID_EV) {
  317. for (i = 0; sonypi_lidev[i].event; i++)
  318. if (sonypi_lidev[i].data == v1) {
  319. event = sonypi_lidev[i].event;
  320. goto found;
  321. }
  322. }
  323. if (verbose)
  324. printk(KERN_WARNING 
  325.        "sonypi: unknown event port1=0x%02x,port2=0x%02xn",v1,v2);
  326. return;
  327. found:
  328. sonypi_pushq(event);
  329. }
  330. /* External camera command (exported to the motion eye v4l driver) */
  331. u8 sonypi_camera_command(int command, u8 value) {
  332. u8 ret = 0;
  333. if (!camera)
  334. return 0;
  335. down(&sonypi_device.lock);
  336. switch(command) {
  337. case SONYPI_COMMAND_GETCAMERA:
  338. ret = sonypi_camera_ready();
  339. break;
  340. case SONYPI_COMMAND_SETCAMERA:
  341. if (value)
  342. sonypi_camera_on();
  343. else
  344. sonypi_camera_off();
  345. break;
  346. case SONYPI_COMMAND_GETCAMERABRIGHTNESS:
  347. ret = sonypi_read(SONYPI_CAMERA_BRIGHTNESS);
  348. break;
  349. case SONYPI_COMMAND_SETCAMERABRIGHTNESS:
  350. sonypi_set(SONYPI_CAMERA_BRIGHTNESS, value);
  351. break;
  352. case SONYPI_COMMAND_GETCAMERACONTRAST:
  353. ret = sonypi_read(SONYPI_CAMERA_CONTRAST);
  354. break;
  355. case SONYPI_COMMAND_SETCAMERACONTRAST:
  356. sonypi_set(SONYPI_CAMERA_CONTRAST, value);
  357. break;
  358. case SONYPI_COMMAND_GETCAMERAHUE:
  359. ret = sonypi_read(SONYPI_CAMERA_HUE);
  360. break;
  361. case SONYPI_COMMAND_SETCAMERAHUE:
  362. sonypi_set(SONYPI_CAMERA_HUE, value);
  363. break;
  364. case SONYPI_COMMAND_GETCAMERACOLOR:
  365. ret = sonypi_read(SONYPI_CAMERA_COLOR);
  366. break;
  367. case SONYPI_COMMAND_SETCAMERACOLOR:
  368. sonypi_set(SONYPI_CAMERA_COLOR, value);
  369. break;
  370. case SONYPI_COMMAND_GETCAMERASHARPNESS:
  371. ret = sonypi_read(SONYPI_CAMERA_SHARPNESS);
  372. break;
  373. case SONYPI_COMMAND_SETCAMERASHARPNESS:
  374. sonypi_set(SONYPI_CAMERA_SHARPNESS, value);
  375. break;
  376. case SONYPI_COMMAND_GETCAMERAPICTURE:
  377. ret = sonypi_read(SONYPI_CAMERA_PICTURE);
  378. break;
  379. case SONYPI_COMMAND_SETCAMERAPICTURE:
  380. sonypi_set(SONYPI_CAMERA_PICTURE, value);
  381. break;
  382. case SONYPI_COMMAND_GETCAMERAAGC:
  383. ret = sonypi_read(SONYPI_CAMERA_AGC);
  384. break;
  385. case SONYPI_COMMAND_SETCAMERAAGC:
  386. sonypi_set(SONYPI_CAMERA_AGC, value);
  387. break;
  388. case SONYPI_COMMAND_GETCAMERADIRECTION:
  389. ret = sonypi_read(SONYPI_CAMERA_STATUS);
  390. ret &= SONYPI_DIRECTION_BACKWARDS;
  391. break;
  392. case SONYPI_COMMAND_GETCAMERAROMVERSION:
  393. ret = sonypi_read(SONYPI_CAMERA_ROMVERSION);
  394. break;
  395. case SONYPI_COMMAND_GETCAMERAREVISION:
  396. ret = sonypi_read(SONYPI_CAMERA_REVISION);
  397. break;
  398. }
  399. up(&sonypi_device.lock);
  400. return ret;
  401. }
  402. static int sonypi_misc_fasync(int fd, struct file *filp, int on) {
  403. int retval;
  404. retval = fasync_helper(fd, filp, on, &sonypi_device.queue.fasync);
  405. if (retval < 0)
  406. return retval;
  407. return 0;
  408. }
  409. static int sonypi_misc_release(struct inode * inode, struct file * file) {
  410. sonypi_misc_fasync(-1, file, 0);
  411. down(&sonypi_device.lock);
  412. sonypi_device.open_count--;
  413. up(&sonypi_device.lock);
  414. return 0;
  415. }
  416. static int sonypi_misc_open(struct inode * inode, struct file * file) {
  417. down(&sonypi_device.lock);
  418. if (sonypi_device.open_count)
  419. goto out;
  420. sonypi_device.open_count++;
  421. /* Flush input queue */
  422. sonypi_initq();
  423. out:
  424. up(&sonypi_device.lock);
  425. return 0;
  426. }
  427. static ssize_t sonypi_misc_read(struct file * file, char * buf, 
  428.                 size_t count, loff_t *pos) {
  429. DECLARE_WAITQUEUE(wait, current);
  430. ssize_t i = count;
  431. unsigned char c;
  432. if (sonypi_emptyq()) {
  433. if (file->f_flags & O_NONBLOCK)
  434. return -EAGAIN;
  435. add_wait_queue(&sonypi_device.queue.proc_list, &wait);
  436. repeat:
  437. set_current_state(TASK_INTERRUPTIBLE);
  438. if (sonypi_emptyq() && !signal_pending(current)) {
  439. schedule();
  440. goto repeat;
  441. }
  442. current->state = TASK_RUNNING;
  443. remove_wait_queue(&sonypi_device.queue.proc_list, &wait);
  444. }
  445. while (i > 0 && !sonypi_emptyq()) {
  446. c = sonypi_pullq();
  447. put_user(c, buf++);
  448. i--;
  449.         }
  450. if (count - i) {
  451. file->f_dentry->d_inode->i_atime = CURRENT_TIME;
  452. return count-i;
  453. }
  454. if (signal_pending(current))
  455. return -ERESTARTSYS;
  456. return 0;
  457. }
  458. static unsigned int sonypi_misc_poll(struct file *file, poll_table * wait) {
  459. poll_wait(file, &sonypi_device.queue.proc_list, wait);
  460. if (!sonypi_emptyq())
  461. return POLLIN | POLLRDNORM;
  462. return 0;
  463. }
  464. static int sonypi_misc_ioctl(struct inode *ip, struct file *fp, 
  465.      unsigned int cmd, unsigned long arg) {
  466. int ret = 0;
  467. u8 val8;
  468. u16 val16;
  469. down(&sonypi_device.lock);
  470. switch (cmd) {
  471. case SONYPI_IOCGBRT:
  472. val8 = sonypi_ecrget(0x96);
  473. if (copy_to_user((u8 *)arg, &val8, sizeof(val8))) {
  474. ret = -EFAULT;
  475. goto out;
  476. }
  477. break;
  478. case SONYPI_IOCSBRT:
  479. if (copy_from_user(&val8, (u8 *)arg, sizeof(val8))) {
  480. ret = -EFAULT;
  481. goto out;
  482. }
  483. sonypi_ecrset(0x96, val8);
  484. break;
  485. case SONYPI_IOCGBAT1CAP:
  486. val16 = sonypi_ecrget16(0xb2);
  487. if (copy_to_user((u16 *)arg, &val16, sizeof(val16))) {
  488. ret = -EFAULT;
  489. goto out;
  490. }
  491. break;
  492. case SONYPI_IOCGBAT1REM:
  493. val16 = sonypi_ecrget16(0xa2);
  494. if (copy_to_user((u16 *)arg, &val16, sizeof(val16))) {
  495. ret = -EFAULT;
  496. goto out;
  497. }
  498. break;
  499. case SONYPI_IOCGBAT2CAP:
  500. val16 = sonypi_ecrget16(0xba);
  501. if (copy_to_user((u16 *)arg, &val16, sizeof(val16))) {
  502. ret = -EFAULT;
  503. goto out;
  504. }
  505. break;
  506. case SONYPI_IOCGBAT2REM:
  507. val16 = sonypi_ecrget16(0xaa);
  508. if (copy_to_user((u16 *)arg, &val16, sizeof(val16))) {
  509. ret = -EFAULT;
  510. goto out;
  511. }
  512. break;
  513. case SONYPI_IOCGBATFLAGS:
  514. val8 = sonypi_ecrget(0x81) & 0x07;
  515. if (copy_to_user((u8 *)arg, &val8, sizeof(val8))) {
  516. ret = -EFAULT;
  517. goto out;
  518. }
  519. break;
  520. case SONYPI_IOCGBLUE:
  521. val8 = sonypi_device.bluetooth_power;
  522. if (copy_to_user((u8 *)arg, &val8, sizeof(val8))) {
  523. ret = -EFAULT;
  524. goto out;
  525. }
  526. break;
  527. case SONYPI_IOCSBLUE:
  528. if (copy_from_user(&val8, (u8 *)arg, sizeof(val8))) {
  529. ret = -EFAULT;
  530. goto out;
  531. }
  532. sonypi_setbluetoothpower(val8);
  533. break;
  534. default:
  535. ret = -EINVAL;
  536. }
  537. out:
  538. up(&sonypi_device.lock);
  539. return ret;
  540. }
  541. static struct file_operations sonypi_misc_fops = {
  542. owner: THIS_MODULE,
  543. read: sonypi_misc_read,
  544. poll: sonypi_misc_poll,
  545. open: sonypi_misc_open,
  546. release: sonypi_misc_release,
  547. fasync:  sonypi_misc_fasync,
  548. ioctl: sonypi_misc_ioctl,
  549. };
  550. struct miscdevice sonypi_misc_device = {
  551. -1, "sonypi", &sonypi_misc_fops
  552. };
  553. static int __devinit sonypi_probe(struct pci_dev *pcidev) {
  554. int i, ret;
  555. struct sonypi_ioport_list *ioport_list;
  556. struct sonypi_irq_list *irq_list;
  557. sonypi_device.dev = pcidev;
  558. if (pcidev)
  559. sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE1;
  560. else
  561. sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2;
  562. sonypi_initq();
  563. init_MUTEX(&sonypi_device.lock);
  564. sonypi_device.bluetooth_power = 0;
  565. if (pcidev && pci_enable_device(pcidev)) {
  566. printk(KERN_ERR "sonypi: pci_enable_device failedn");
  567. ret = -EIO;
  568. goto out1;
  569. }
  570. sonypi_misc_device.minor = (minor == -1) ? 
  571. MISC_DYNAMIC_MINOR : minor;
  572. if ((ret = misc_register(&sonypi_misc_device))) {
  573. printk(KERN_ERR "sonypi: misc_register failedn");
  574. goto out1;
  575. }
  576. if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) {
  577. ioport_list = sonypi_type2_ioport_list;
  578. sonypi_device.region_size = SONYPI_TYPE2_REGION_SIZE;
  579. irq_list = sonypi_type2_irq_list;
  580. }
  581. else {
  582. ioport_list = sonypi_type1_ioport_list;
  583. sonypi_device.region_size = SONYPI_TYPE1_REGION_SIZE;
  584. irq_list = sonypi_type1_irq_list;
  585. }
  586. for (i = 0; ioport_list[i].port1; i++) {
  587. if (request_region(ioport_list[i].port1, 
  588.    sonypi_device.region_size, 
  589.    "Sony Programable I/O Device")) {
  590. /* get the ioport */
  591. sonypi_device.ioport1 = ioport_list[i].port1;
  592. sonypi_device.ioport2 = ioport_list[i].port2;
  593. break;
  594. }
  595. }
  596. if (!sonypi_device.ioport1) {
  597. printk(KERN_ERR "sonypi: request_region failedn");
  598. ret = -ENODEV;
  599. goto out2;
  600. }
  601. for (i = 0; irq_list[i].irq; i++) {
  602. if (!request_irq(irq_list[i].irq, sonypi_irq, 
  603.  SA_SHIRQ, "sonypi", sonypi_irq)) {
  604. sonypi_device.irq = irq_list[i].irq;
  605. sonypi_device.bits = irq_list[i].bits;
  606. break;
  607. }
  608. }
  609. if (!sonypi_device.irq ) {
  610. printk(KERN_ERR "sonypi: request_irq failedn");
  611. ret = -ENODEV;
  612. goto out3;
  613. }
  614. #if !defined(CONFIG_ACPI)
  615. /* Enable ACPI mode to get Fn key events */
  616. if (fnkeyinit)
  617. outb(0xf0, 0xb2);
  618. #endif
  619. if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
  620. sonypi_type2_srs();
  621. else
  622. sonypi_type1_srs();
  623. sonypi_call1(0x82);
  624. sonypi_call2(0x81, 0xff);
  625. if (compat)
  626. sonypi_call1(0x92); 
  627. else
  628. sonypi_call1(0x82);
  629. printk(KERN_INFO "sonypi: Sony Programmable I/O Controller Driver v%d.%d.n",
  630.        SONYPI_DRIVER_MAJORVERSION,
  631.        SONYPI_DRIVER_MINORVERSION);
  632. printk(KERN_INFO "sonypi: detected %s model, "
  633.        "camera = %s, compat = %sn",
  634.        (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) ?
  635. "type1" : "type2",
  636.        camera ? "on" : "off",
  637.        compat ? "on" : "off");
  638. printk(KERN_INFO "sonypi: enabled at irq=%d, port1=0x%x, port2=0x%xn",
  639.        sonypi_device.irq, 
  640.        sonypi_device.ioport1, sonypi_device.ioport2);
  641. if (minor == -1)
  642. printk(KERN_INFO "sonypi: device allocated minor is %dn",
  643.        sonypi_misc_device.minor);
  644. return 0;
  645. out3:
  646. release_region(sonypi_device.ioport1, sonypi_device.region_size);
  647. out2:
  648. misc_deregister(&sonypi_misc_device);
  649. out1:
  650. return ret;
  651. }
  652. static void __devexit sonypi_remove(void) {
  653. sonypi_call2(0x81, 0); /* make sure we don't get any more events */
  654. if (camera)
  655. sonypi_camera_off();
  656. if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
  657. sonypi_type2_dis();
  658. else
  659. sonypi_type1_dis();
  660. #if !defined(CONFIG_ACPI)
  661. /* disable ACPI mode */
  662. if (fnkeyinit)
  663. outb(0xf1, 0xb2);
  664. #endif
  665. free_irq(sonypi_device.irq, sonypi_irq);
  666. release_region(sonypi_device.ioport1, sonypi_device.region_size);
  667. misc_deregister(&sonypi_misc_device);
  668. printk(KERN_INFO "sonypi: removed.n");
  669. }
  670. static int __init sonypi_init_module(void) {
  671. struct pci_dev *pcidev = NULL;
  672. if (is_sony_vaio_laptop) {
  673. pcidev = pci_find_device(PCI_VENDOR_ID_INTEL, 
  674.  PCI_DEVICE_ID_INTEL_82371AB_3, 
  675.  NULL);
  676. return sonypi_probe(pcidev);
  677. }
  678. else
  679. return -ENODEV;
  680. }
  681. static void __exit sonypi_cleanup_module(void) {
  682. sonypi_remove();
  683. }
  684. #ifndef MODULE
  685. static int __init sonypi_setup(char *str)  {
  686. int ints[6];
  687. str = get_options(str, ARRAY_SIZE(ints), ints);
  688. if (ints[0] <= 0) 
  689. goto out;
  690. minor = ints[1];
  691. if (ints[0] == 1)
  692. goto out;
  693. verbose = ints[2];
  694. if (ints[0] == 2)
  695. goto out;
  696. fnkeyinit = ints[3];
  697. if (ints[0] == 3)
  698. goto out;
  699. camera = ints[4];
  700. if (ints[0] == 4)
  701. goto out;
  702. compat = ints[5];
  703. out:
  704. return 1;
  705. }
  706. __setup("sonypi=", sonypi_setup);
  707. #endif /* !MODULE */
  708. /* Module entry points */
  709. module_init(sonypi_init_module);
  710. module_exit(sonypi_cleanup_module);
  711. MODULE_AUTHOR("Stelian Pop <stelian.pop@fr.alcove.com>");
  712. MODULE_DESCRIPTION("Sony Programmable I/O Control Device driver");
  713. MODULE_LICENSE("GPL");
  714. MODULE_PARM(minor,"i");
  715. MODULE_PARM_DESC(minor, "minor number of the misc device, default is -1 (automatic)");
  716. MODULE_PARM(verbose,"i");
  717. MODULE_PARM_DESC(verbose, "be verbose, default is 0 (no)");
  718. MODULE_PARM(fnkeyinit,"i");
  719. MODULE_PARM_DESC(fnkeyinit, "set this if your Fn keys do not generate any event");
  720. MODULE_PARM(camera,"i");
  721. MODULE_PARM_DESC(camera, "set this if you have a MotionEye camera (PictureBook series)");
  722. MODULE_PARM(compat,"i");
  723. MODULE_PARM_DESC(compat, "set this if you want to enable backward compatibility mode");
  724. EXPORT_SYMBOL(sonypi_camera_command);