sony-pic.c 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * This comment was taken from the original sony-laptop code
  4. *
  5. * ACPI Sony Notebook Control Driver (SNC and SPIC)
  6. *
  7. * Copyright (C) 2004-2005 Stelian Pop <stelian@popies.net>
  8. * Copyright (C) 2007-2009 Mattia Dongili <malattia@linux.it>
  9. *
  10. * Parts of this driver inspired from asus_acpi.c and ibm_acpi.c
  11. * which are copyrighted by their respective authors.
  12. *
  13. * The SNY6001 driver part is based on the sonypi driver which includes
  14. * material from:
  15. *
  16. * Copyright (C) 2001-2005 Stelian Pop <stelian@popies.net>
  17. *
  18. * Copyright (C) 2005 Narayanan R S <nars@kadamba.org>
  19. *
  20. * Copyright (C) 2001-2002 Alcôve <www.alcove.com>
  21. *
  22. * Copyright (C) 2001 Michael Ashley <m.ashley@unsw.edu.au>
  23. *
  24. * Copyright (C) 2001 Junichi Morita <jun1m@mars.dti.ne.jp>
  25. *
  26. * Copyright (C) 2000 Takaya Kinjo <t-kinjo@tc4.so-net.ne.jp>
  27. *
  28. * Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com>
  29. *
  30. * Earlier work by Werner Almesberger, Paul `Rusty' Russell and Paul Mackerras.
  31. */
  32. #include <linux/acpi.h>
  33. #include <linux/pci.h>
  34. #include <linux/platform_device.h>
  35. #include <linux/delay.h>
  36. #include <linux/dmi.h>
  37. #include <linux/input.h>
  38. #include "sony-pic.h"
  39. /***********************************************************
  40. * *
  41. * This module based on sony-laptop from kernel sources *
  42. * Sony Programmable IO Control - SPIC (SNY6001) *
  43. * *
  44. ***********************************************************/
  45. int sonypi_compat_init( void );
  46. void sonypi_compat_exit(void);
  47. void sonypi_compat_report_event( u8 event );
  48. int compat;// = 0
  49. module_param(compat, int, 0444);
  50. MODULE_PARM_DESC( compat, "set this if you want to enable backward compatibility mode" );
  51. static int camera; /* = 0 */
  52. module_param(camera, int, 0444);
  53. MODULE_PARM_DESC(camera,
  54. "set this to 1 to enable Motion Eye camera controls "
  55. "(only use it if you have a C1VE or C1VN model)");
  56. /********************
  57. * INPUT DEVICE *
  58. ********************/
  59. static void vgnux_input_sendkey( int key ){
  60. if( key ){
  61. input_report_key( vgnux_input_device, key, 1 );
  62. input_sync( vgnux_input_device );
  63. input_report_key( vgnux_input_device, key, 0 );
  64. input_sync( vgnux_input_device );
  65. }
  66. }
  67. static int vgnux_register_input( void ){
  68. int err = 0;
  69. int i;
  70. vgnux_input_device = input_allocate_device();
  71. if( !vgnux_input_device )return -ENOMEM;
  72. vgnux_input_device->name = KBUILD_MODNAME;
  73. vgnux_input_device->id.bustype = BUS_ISA;
  74. vgnux_input_device->id.vendor = PCI_VENDOR_ID_SONY;
  75. vgnux_input_device->keycodesize = sizeof( vgnux_input_keycode_map[0] );
  76. vgnux_input_device->keycodemax = ARRAY_SIZE( vgnux_input_keycode_map );
  77. vgnux_input_device->keycode = &vgnux_input_keycode_map;
  78. for( i = 0; vgnux_input_keycode_map[i] != KEY_RESERVED; i++ ){
  79. input_set_capability( vgnux_input_device, EV_KEY, vgnux_input_keycode_map[i] );
  80. }
  81. err = input_register_device( vgnux_input_device );
  82. if( err ) input_free_device( vgnux_input_device );
  83. return err;
  84. }
  85. static void vgnux_unregister_input( void ){
  86. input_unregister_device( vgnux_input_device );
  87. }
  88. /************************
  89. * Platform Device *
  90. ************************/
  91. static int sony_pf_add( void ){
  92. int ret = 0;
  93. ret = platform_driver_register( &sony_pf_driver );
  94. if (ret) goto out;
  95. sony_pf_device = platform_device_alloc( KBUILD_MODNAME, -1 );
  96. if (!sony_pf_device) {
  97. ret = -ENOMEM;
  98. goto out_platform_registered;
  99. }
  100. ret = platform_device_add(sony_pf_device);
  101. if (ret) goto out_platform_alloced;
  102. return 0;
  103. out_platform_alloced:
  104. platform_device_put(sony_pf_device);
  105. sony_pf_device = NULL;
  106. out_platform_registered:
  107. platform_driver_unregister(&sony_pf_driver);
  108. out:
  109. return ret;
  110. }
  111. static void sony_pf_remove(void){
  112. platform_device_unregister(sony_pf_device);
  113. platform_driver_unregister(&sony_pf_driver);
  114. }
  115. /*****************************
  116. * low level spic calls *
  117. ******************************/
  118. #define ITERATIONS_LONG 10000
  119. #define ITERATIONS_SHORT 10
  120. #define wait_on_command(command, iterations) { \
  121. unsigned int n = iterations; \
  122. while( --n && (command) )udelay(1); \
  123. if (!n) printk( KERN_WARNING "[%s] command failed at %s : %s (line %d)\n", \
  124. KBUILD_MODNAME, __FILE__, __func__, __LINE__); \
  125. }
  126. u8 sony_pic_call1(u8 dev){
  127. u8 v1, v2;
  128. wait_on_command( inb_p( spic_dev.cur_ioport->io1.minimum + 4 ) & 2, ITERATIONS_LONG );
  129. outb( dev, spic_dev.cur_ioport->io1.minimum + 4 );
  130. v1 = inb_p( spic_dev.cur_ioport->io1.minimum + 4 );
  131. v2 = inb_p( spic_dev.cur_ioport->io1.minimum );
  132. //printk( KERN_NOTICE "[%s] %s(0x%.2x): 0x%.4x\n", KBUILD_MODNAME, __FUNCTION__, dev, (v2 << 8) | v1 );
  133. return v2;
  134. }
  135. u8 sony_pic_call2(u8 dev, u8 fn){
  136. u8 v1;
  137. wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG );
  138. outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
  139. wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG );
  140. outb(fn, spic_dev.cur_ioport->io1.minimum);
  141. v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
  142. //printk( KERN_NOTICE "[%s] %s(0x%.2x - 0x%.2x): 0x%.4x\n", KBUILD_MODNAME, __FUNCTION__, dev, fn, v1 );
  143. return v1;
  144. }
  145. static u8 sony_pic_call3(u8 dev, u8 fn, u8 v){
  146. u8 v1;
  147. wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
  148. outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
  149. wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
  150. outb(fn, spic_dev.cur_ioport->io1.minimum);
  151. wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
  152. outb(v, spic_dev.cur_ioport->io1.minimum);
  153. v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
  154. //printk( KERN_NOTICE "[%s] %s(0x%.2x - 0x%.2x - 0x%.2x): 0x%.4x\n", KBUILD_MODNAME, __FUNCTION__, dev, fn, v, v1 );
  155. return v1;
  156. }
  157. /*******************
  158. * CAMERA *
  159. *******************/
  160. //only for export
  161. static int __sony_pic_camera_ready(void){
  162. u8 v;
  163. v = sony_pic_call2(0x8f, SONYPI_CAMERA_STATUS);
  164. return (v != 0xff && (v & SONYPI_CAMERA_STATUS_READY));
  165. }
  166. static int __sony_pic_camera_off(void){
  167. if (!camera) {
  168. pr_warn("camera control not enabled\n");
  169. return -ENODEV;
  170. }
  171. wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE,
  172. SONYPI_CAMERA_MUTE_MASK),
  173. ITERATIONS_SHORT);
  174. if (spic_dev.camera_power) {
  175. sony_pic_call2(0x91, 0);
  176. spic_dev.camera_power = 0;
  177. }
  178. return 0;
  179. }
  180. static int __sony_pic_camera_on(void){
  181. int i, j, x;
  182. if (!camera) {
  183. pr_warn("camera control not enabled\n");
  184. return -ENODEV;
  185. }
  186. if (spic_dev.camera_power)return 0;
  187. for (j = 5; j > 0; j--) {
  188. for (x = 0; x < 100 && sony_pic_call2(0x91, 0x1); x++)
  189. msleep(10);
  190. sony_pic_call1(0x93);
  191. for (i = 400; i > 0; i--) {
  192. if( __sony_pic_camera_ready() ) break;
  193. msleep(10);
  194. }
  195. if( i ) break;
  196. }
  197. if (j == 0) {
  198. pr_warn("failed to power on camera\n");
  199. return -ENODEV;
  200. }
  201. wait_on_command( sony_pic_call3(0x90, SONYPI_CAMERA_CONTROL, 0x5a), ITERATIONS_SHORT );
  202. spic_dev.camera_power = 1;
  203. return 0;
  204. }
  205. /* External camera command (exported to the motion eye v4l driver) */
  206. int sony_pic_camera_command(int command, u8 value){
  207. if (!camera) return -EIO;
  208. mutex_lock(&spic_dev.lock);
  209. switch (command) {
  210. case SONY_PIC_COMMAND_SETCAMERA:
  211. if( value ) __sony_pic_camera_on();
  212. else __sony_pic_camera_off();
  213. break;
  214. case SONY_PIC_COMMAND_SETCAMERABRIGHTNESS:
  215. wait_on_command( sony_pic_call3( 0x90, SONYPI_CAMERA_BRIGHTNESS, value ), ITERATIONS_SHORT );
  216. break;
  217. case SONY_PIC_COMMAND_SETCAMERACONTRAST:
  218. wait_on_command( sony_pic_call3( 0x90, SONYPI_CAMERA_CONTRAST, value ), ITERATIONS_SHORT );
  219. break;
  220. case SONY_PIC_COMMAND_SETCAMERAHUE:
  221. wait_on_command( sony_pic_call3( 0x90, SONYPI_CAMERA_HUE, value ), ITERATIONS_SHORT );
  222. break;
  223. case SONY_PIC_COMMAND_SETCAMERACOLOR:
  224. wait_on_command( sony_pic_call3( 0x90, SONYPI_CAMERA_COLOR, value ), ITERATIONS_SHORT );
  225. break;
  226. case SONY_PIC_COMMAND_SETCAMERASHARPNESS:
  227. wait_on_command( sony_pic_call3( 0x90, SONYPI_CAMERA_SHARPNESS, value ), ITERATIONS_SHORT );
  228. break;
  229. case SONY_PIC_COMMAND_SETCAMERAPICTURE:
  230. wait_on_command( sony_pic_call3( 0x90, SONYPI_CAMERA_PICTURE, value ), ITERATIONS_SHORT );
  231. break;
  232. case SONY_PIC_COMMAND_SETCAMERAAGC:
  233. wait_on_command( sony_pic_call3( 0x90, SONYPI_CAMERA_AGC, value ), ITERATIONS_SHORT );
  234. break;
  235. default:
  236. pr_err("sony_pic_camera_command invalid: %d\n", command);
  237. break;
  238. }
  239. mutex_unlock(&spic_dev.lock);
  240. return 0;
  241. }
  242. EXPORT_SYMBOL(sony_pic_camera_command);
  243. /***************************************************************
  244. * gprs/edge modem (SZ460N and SZ210P), thanks to Joshua Wise *
  245. ***************************************************************/
  246. static void __sony_pic_set_wwanpower( u8 state ){
  247. state = !!state;
  248. if ( spic_dev.wwan_power == state ) return;
  249. sony_pic_call2( 0xB0, state );
  250. sony_pic_call1( 0x82 );
  251. spic_dev.wwan_power = state;
  252. }
  253. static ssize_t sony_pic_wwanpower_store( struct device *dev, struct device_attribute *attr, const char *buffer, size_t count ){
  254. unsigned long value;
  255. if (count > 31) return -EINVAL;
  256. if (kstrtoul(buffer, 10, &value)) return -EINVAL;
  257. mutex_lock(&spic_dev.lock);
  258. __sony_pic_set_wwanpower(value);
  259. mutex_unlock(&spic_dev.lock);
  260. return count;
  261. }
  262. static ssize_t sony_pic_wwanpower_show(struct device *dev, struct device_attribute *attr, char *buffer){
  263. ssize_t count;
  264. mutex_lock(&spic_dev.lock);
  265. count = sysfs_emit( buffer, "%d\n", spic_dev.wwan_power );
  266. mutex_unlock(&spic_dev.lock);
  267. return count;
  268. }
  269. /************************************
  270. * bluetooth subsystem power state *
  271. ************************************/
  272. static void __sony_pic_set_bluetoothpower(u8 state){
  273. state = !!state;
  274. if (spic_dev.bluetooth_power == state) return;
  275. sony_pic_call2(0x96, state);
  276. sony_pic_call1(0x82);
  277. spic_dev.bluetooth_power = state;
  278. }
  279. static ssize_t sony_pic_bluetoothpower_store( struct device *dev, struct device_attribute *attr, const char *buffer, size_t count ){
  280. unsigned long value;
  281. if (count > 31) return -EINVAL;
  282. if (kstrtoul(buffer, 10, &value)) return -EINVAL;
  283. mutex_lock(&spic_dev.lock);
  284. __sony_pic_set_bluetoothpower(value);
  285. mutex_unlock(&spic_dev.lock);
  286. return count;
  287. }
  288. static ssize_t sony_pic_bluetoothpower_show(struct device *dev, struct device_attribute *attr, char *buffer){
  289. ssize_t count = 0;
  290. mutex_lock(&spic_dev.lock);
  291. count = sysfs_emit( buffer, "%d\n", spic_dev.bluetooth_power );
  292. mutex_unlock(&spic_dev.lock);
  293. return count;
  294. }
  295. /***********************************************************
  296. * FAN0 information (reverse engineered from ACPI tables) *
  297. ***********************************************************/
  298. #define SONY_PIC_FAN0_STATUS 0x93
  299. static int sony_pic_set_fanspeed(unsigned long value){
  300. return ec_write(SONY_PIC_FAN0_STATUS, value);
  301. }
  302. static int sony_pic_get_fanspeed(u8 *value){
  303. return ec_read(SONY_PIC_FAN0_STATUS, value);
  304. }
  305. static ssize_t sony_pic_fanspeed_store( struct device *dev, struct device_attribute *attr, const char *buffer, size_t count ){
  306. unsigned long value;
  307. if (count > 31)return -EINVAL;
  308. if (kstrtoul(buffer, 10, &value))return -EINVAL;
  309. if (sony_pic_set_fanspeed(value))return -EIO;
  310. return count;
  311. }
  312. static ssize_t sony_pic_fanspeed_show( struct device *dev, struct device_attribute *attr, char *buffer ){
  313. u8 value = 0;
  314. if (sony_pic_get_fanspeed(&value)) return -EIO;
  315. return sysfs_emit( buffer, "%d\n", value );
  316. }
  317. /************
  318. * ATTRS *
  319. ************/
  320. #define SPIC_ATTR(_name, _mode) \
  321. struct device_attribute spic_attr_##_name = __ATTR(_name, \
  322. _mode, sony_pic_## _name ##_show, \
  323. sony_pic_## _name ##_store)
  324. static SPIC_ATTR(bluetoothpower, 0644);
  325. static SPIC_ATTR(wwanpower, 0644);
  326. static SPIC_ATTR(fanspeed, 0644);
  327. static struct attribute *spic_attributes[] = {
  328. &spic_attr_bluetoothpower.attr,
  329. &spic_attr_wwanpower.attr,
  330. &spic_attr_fanspeed.attr,
  331. NULL
  332. };
  333. static const struct attribute_group spic_attribute_group = {
  334. .attrs = spic_attributes
  335. };
  336. /***********************************
  337. * ISR: some event is available *
  338. ***********************************/
  339. irqreturn_t sony_pic_irq_handler( int irq, void *dev_id ){
  340. int i, j;
  341. u8 ev = 0;
  342. u8 data_mask = 0;
  343. struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id;
  344. ev = inb_p( dev->cur_ioport->io1.minimum );
  345. if( dev->cur_ioport->io2.minimum ) data_mask = inb_p( dev->cur_ioport->io2.minimum );
  346. else data_mask = inb_p( dev->cur_ioport->io1.minimum + dev->evport_offset );
  347. /*
  348. printk( KERN_NOTICE "[%s] event [%.2x] mask [%.2x] port 0x%.4x(+0x%.2x)\n",
  349. KBUILD_MODNAME,
  350. ev,
  351. data_mask,
  352. dev->cur_ioport->io1.minimum,
  353. dev->evport_offset
  354. );
  355. */
  356. if (ev == 0x00 || ev == 0xff) return IRQ_HANDLED;
  357. for (i = 0; dev->event_types[i].data; i++) {
  358. if( data_mask != dev->event_types[i].data ) continue;
  359. for( j = 0; dev->event_types[i].events[j].data; j++ ) {
  360. if( ev == dev->event_types[i].events[j].data ) {
  361. vgnux_input_sendkey( dev->event_types[i].events[j].key );
  362. //events were thrown out as unnecessary
  363. //sonypi_compat_report_event( dev->event_types[i].events[j].event );
  364. return IRQ_HANDLED;
  365. }
  366. }
  367. }
  368. //Still not able to decode the event try to pass it over to the minidriver
  369. if( dev->handle_irq && dev->handle_irq(data_mask, ev) == 0 ) return IRQ_HANDLED;
  370. printk( KERN_WARNING "[%s] unknown event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
  371. KBUILD_MODNAME,
  372. ev,
  373. data_mask,
  374. dev->cur_ioport->io1.minimum,
  375. dev->evport_offset
  376. );
  377. return IRQ_HANDLED;
  378. }
  379. static int type3_handle_irq( const u8 data_mask, const u8 ev ){
  380. /*
  381. * 0x31 could mean we have to take some extra action and wait for
  382. * the next irq for some Type3 models, it will generate a new
  383. * irq and we can read new data from the device:
  384. * - 0x5c and 0x5f requires 0xA0
  385. * - 0x61 requires 0xB3
  386. */
  387. if( data_mask == 0x31 ){
  388. if ( ev == 0x5c || ev == 0x5f ) sony_pic_call1( 0xA0 );
  389. else if( ev == 0x61 ) sony_pic_call1( 0xB3 );
  390. return 0;
  391. }
  392. return 1;
  393. }
  394. /***********************
  395. * ACPI RESOURCES *
  396. ***********************/
  397. static acpi_status sony_pic_read_possible_resource( struct acpi_resource *resource, void *context ){
  398. u32 i;
  399. struct sony_pic_dev *dev = (struct sony_pic_dev *)context;
  400. switch (resource->type) {
  401. case ACPI_RESOURCE_TYPE_START_DEPENDENT:
  402. {
  403. /* start IO enumeration */
  404. struct sony_pic_ioport *ioport = kzalloc(sizeof(*ioport), GFP_KERNEL);
  405. if (!ioport)
  406. return AE_ERROR;
  407. list_add(&ioport->list, &dev->ioports);
  408. return AE_OK;
  409. }
  410. case ACPI_RESOURCE_TYPE_END_DEPENDENT:
  411. /* end IO enumeration */
  412. return AE_OK;
  413. case ACPI_RESOURCE_TYPE_IRQ:
  414. {
  415. struct acpi_resource_irq *p = &resource->data.irq;
  416. struct sony_pic_irq *interrupt = NULL;
  417. if (!p || !p->interrupt_count) {
  418. /*
  419. * IRQ descriptors may have no IRQ# bits set,
  420. * particularly those those w/ _STA disabled
  421. */
  422. printk( KERN_NOTICE "[%s] Blank IRQ resource\n", KBUILD_MODNAME );
  423. return AE_OK;
  424. }
  425. for (i = 0; i < p->interrupt_count; i++) {
  426. if (!p->interrupts[i]) {
  427. pr_warn( "Invalid IRQ %d\n", p->interrupts[i] );
  428. continue;
  429. }
  430. interrupt = kzalloc(sizeof(*interrupt), GFP_KERNEL );
  431. if( !interrupt ) return AE_ERROR;
  432. list_add(&interrupt->list, &dev->interrupts);
  433. interrupt->irq.triggering = p->triggering;
  434. interrupt->irq.polarity = p->polarity;
  435. interrupt->irq.shareable = p->shareable;
  436. interrupt->irq.interrupt_count = 1;
  437. interrupt->irq.interrupts[0] = p->interrupts[i];
  438. }
  439. return AE_OK;
  440. }
  441. case ACPI_RESOURCE_TYPE_IO:
  442. {
  443. struct acpi_resource_io *io = &resource->data.io;
  444. struct sony_pic_ioport *ioport =
  445. list_first_entry(&dev->ioports, struct sony_pic_ioport, list);
  446. if (!io) {
  447. printk( KERN_NOTICE "[%s] Blank IO resource\n", KBUILD_MODNAME );
  448. return AE_OK;
  449. }
  450. if (!ioport->io1.minimum) {
  451. memcpy(&ioport->io1, io, sizeof(*io));
  452. printk( KERN_NOTICE "[%s] IO1 at 0x%.4x (0x%.2x)\n", KBUILD_MODNAME, ioport->io1.minimum, ioport->io1.address_length );
  453. }
  454. else if (!ioport->io2.minimum) {
  455. memcpy(&ioport->io2, io, sizeof(*io));
  456. printk( KERN_NOTICE "[%s] IO2 at 0x%.4x (0x%.2x)\n", KBUILD_MODNAME, ioport->io2.minimum, ioport->io2.address_length );
  457. }
  458. else {
  459. pr_err( "Unknown SPIC Type, more than 2 IO Ports\n" );
  460. return AE_ERROR;
  461. }
  462. return AE_OK;
  463. }
  464. case ACPI_RESOURCE_TYPE_END_TAG:
  465. return AE_OK;
  466. default:
  467. printk( KERN_NOTICE "[%s] Resource %d isn't an IRQ nor an IO port\n", KBUILD_MODNAME, resource->type );
  468. return AE_CTRL_TERMINATE;
  469. }
  470. }
  471. static int sony_pic_possible_resources( struct acpi_device *device ){
  472. int result = 0;
  473. acpi_status status = AE_OK;
  474. if (!device) return -EINVAL;
  475. /* get device status */
  476. /* see acpi_pci_link_get_current acpi_pci_link_get_possible */
  477. printk( KERN_NOTICE "[%s] Evaluating _STA\n", KBUILD_MODNAME );
  478. result = acpi_bus_get_status(device);
  479. if( result ){
  480. pr_warn("Unable to read status\n");
  481. goto end;
  482. }
  483. if( !device->status.enabled ) printk( KERN_NOTICE "[%s] Device disabled\n", KBUILD_MODNAME );
  484. else printk( KERN_NOTICE "[%s] Device enabled\n", KBUILD_MODNAME );
  485. //Query and parse 'method'
  486. printk( KERN_NOTICE "[%s] Evaluating %s\n", KBUILD_MODNAME, METHOD_NAME__PRS );
  487. status = acpi_walk_resources( device->handle, METHOD_NAME__PRS, sony_pic_read_possible_resource, &spic_dev );
  488. if( ACPI_FAILURE(status) ){
  489. pr_warn( "Failure evaluating %s\n", METHOD_NAME__PRS );
  490. result = -ENODEV;
  491. }
  492. end:
  493. return result;
  494. }
  495. /***************************
  496. * DETECT DEVICE TYPE *
  497. ***************************/
  498. static void sony_pic_detect_device_type( struct sony_pic_dev *dev ){
  499. struct pci_dev *pcidev;
  500. pcidev = pci_get_device( PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL );
  501. if( pcidev ){
  502. dev->model = SONYPI_DEVICE_TYPE1;
  503. dev->evport_offset = SONYPI_TYPE1_OFFSET;
  504. dev->event_types = dummy_events;
  505. goto out;
  506. }
  507. pcidev = pci_get_device( PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, NULL );
  508. if( pcidev ){
  509. dev->model = SONYPI_DEVICE_TYPE2;
  510. dev->evport_offset = SONYPI_TYPE2_OFFSET;
  511. dev->event_types = dummy_events;
  512. goto out;
  513. }
  514. pcidev = pci_get_device( PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, NULL );//VGN-UX
  515. if( pcidev ){
  516. dev->model = SONYPI_DEVICE_TYPE3;
  517. dev->handle_irq = type3_handle_irq;
  518. dev->evport_offset = SONYPI_TYPE3_OFFSET;
  519. //dev->event_types = type3_events;
  520. dev->event_types = vgnux_events;
  521. goto out;
  522. }
  523. pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_4, NULL );
  524. if( pcidev ){
  525. dev->model = SONYPI_DEVICE_TYPE3;
  526. dev->handle_irq = type3_handle_irq;
  527. dev->evport_offset = SONYPI_TYPE3_OFFSET;
  528. dev->event_types = dummy_events;
  529. goto out;
  530. }
  531. pcidev = pci_get_device( PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_1, NULL );
  532. if( pcidev ){
  533. dev->model = SONYPI_DEVICE_TYPE3;
  534. dev->handle_irq = type3_handle_irq;
  535. dev->evport_offset = SONYPI_TYPE3_OFFSET;
  536. dev->event_types = dummy_events;
  537. goto out;
  538. }
  539. /* default */
  540. dev->model = SONYPI_DEVICE_TYPE2;
  541. dev->evport_offset = SONYPI_TYPE2_OFFSET;
  542. dev->event_types = dummy_events;
  543. out:
  544. pci_dev_put(pcidev);
  545. pr_info("[%s]detected Type%d model\n",
  546. KBUILD_MODNAME,
  547. dev->model == SONYPI_DEVICE_TYPE1 ? 1 :
  548. dev->model == SONYPI_DEVICE_TYPE2 ? 2 : 3 );
  549. }
  550. /*************************
  551. * SPIC DEVICE INIT *
  552. *************************/
  553. //Based on drivers/acpi/pci_link.c:acpi_pci_link_set
  554. //Call _SRS to set current resources
  555. static int sony_pic_enable( struct acpi_device *device, struct sony_pic_ioport *ioport, struct sony_pic_irq *irq ){
  556. acpi_status status;
  557. int result = 0;
  558. /* Type 1 resource layout is:
  559. * IO
  560. * IO
  561. * IRQNoFlags
  562. * End
  563. *
  564. * Type 2 and 3 resource layout is:
  565. * IO
  566. * IRQNoFlags
  567. * End
  568. */
  569. struct {
  570. struct acpi_resource res1;
  571. struct acpi_resource res2;
  572. struct acpi_resource res3;
  573. struct acpi_resource res4;
  574. } *resource;
  575. struct acpi_buffer buffer = { 0, NULL };
  576. if (!ioport || !irq) return -EINVAL;
  577. /* init acpi_buffer */
  578. resource = kzalloc(sizeof(*resource) + 1, GFP_KERNEL);
  579. if (!resource) return -ENOMEM;
  580. buffer.length = sizeof(*resource) + 1;
  581. buffer.pointer = resource;
  582. /* setup Type 1 resources */
  583. if (spic_dev.model == SONYPI_DEVICE_TYPE1) {
  584. /* setup io resources */
  585. resource->res1.type = ACPI_RESOURCE_TYPE_IO;
  586. resource->res1.length = sizeof(struct acpi_resource);
  587. memcpy(&resource->res1.data.io, &ioport->io1, sizeof(struct acpi_resource_io));
  588. resource->res2.type = ACPI_RESOURCE_TYPE_IO;
  589. resource->res2.length = sizeof(struct acpi_resource);
  590. memcpy(&resource->res2.data.io, &ioport->io2, sizeof(struct acpi_resource_io));
  591. /* setup irq resource */
  592. resource->res3.type = ACPI_RESOURCE_TYPE_IRQ;
  593. resource->res3.length = sizeof(struct acpi_resource);
  594. memcpy(&resource->res3.data.irq, &irq->irq, sizeof(struct acpi_resource_irq));
  595. /* we requested a shared irq */
  596. resource->res3.data.irq.shareable = ACPI_SHARED;
  597. resource->res4.type = ACPI_RESOURCE_TYPE_END_TAG;
  598. resource->res4.length = sizeof(struct acpi_resource);
  599. }
  600. /* setup Type 2/3 resources */
  601. else {
  602. /* setup io resource */
  603. resource->res1.type = ACPI_RESOURCE_TYPE_IO;
  604. resource->res1.length = sizeof(struct acpi_resource);
  605. memcpy(&resource->res1.data.io, &ioport->io1,
  606. sizeof(struct acpi_resource_io));
  607. /* setup irq resource */
  608. resource->res2.type = ACPI_RESOURCE_TYPE_IRQ;
  609. resource->res2.length = sizeof(struct acpi_resource);
  610. memcpy(&resource->res2.data.irq, &irq->irq, sizeof(struct acpi_resource_irq));
  611. /* we requested a shared irq */
  612. resource->res2.data.irq.shareable = ACPI_SHARED;
  613. resource->res3.type = ACPI_RESOURCE_TYPE_END_TAG;
  614. resource->res3.length = sizeof(struct acpi_resource);
  615. }
  616. /* Attempt to set the resource */
  617. printk( KERN_NOTICE "[%s] Evaluating _SRS\n", KBUILD_MODNAME );
  618. status = acpi_set_current_resources(device->handle, &buffer);
  619. /* check for total failure */
  620. if (ACPI_FAILURE(status)) {
  621. pr_err("Error evaluating _SRS\n");
  622. result = -ENODEV;
  623. goto end;
  624. }
  625. /* Necessary device initializations calls (from sonypi) */
  626. sony_pic_call1(0x82);
  627. sony_pic_call2(0x81, 0xff);
  628. sony_pic_call1(compat ? 0x92 : 0x82);
  629. end:
  630. kfree(resource);
  631. return result;
  632. }
  633. //Disable the spic device by calling its _DIS method
  634. static int sony_pic_disable( struct acpi_device *device ){
  635. acpi_status ret = acpi_evaluate_object( device->handle, "_DIS", NULL, NULL );
  636. if( ACPI_FAILURE(ret) && ret != AE_NOT_FOUND ) return -ENXIO;
  637. printk( KERN_NOTICE "[%s] Device disabled\n", KBUILD_MODNAME );
  638. return 0;
  639. }
  640. static int sony_pic_add( struct acpi_device* device ) {
  641. int result;
  642. struct sony_pic_ioport *io, *tmp_io;
  643. struct sony_pic_irq *irq, *tmp_irq;
  644. printk( KERN_NOTICE "[%s] SPIC setup...\n", KBUILD_MODNAME );
  645. spic_dev.acpi_dev = device;
  646. strcpy(acpi_device_class(device), "sony/hotkey");
  647. sony_pic_detect_device_type(&spic_dev);
  648. mutex_init(&spic_dev.lock);
  649. /* read _PRS resources */
  650. result = sony_pic_possible_resources( device );
  651. if( result ){
  652. pr_err( "[%s]Unable to read possible resources\n", KBUILD_MODNAME );
  653. goto err_free_resources;
  654. }
  655. //setup input device
  656. result = vgnux_register_input();
  657. if( result ){
  658. pr_err("[%s]Unable to create input device\n", KBUILD_MODNAME );
  659. goto err_free_resources;
  660. }
  661. result = sonypi_compat_init();
  662. if( result ) goto err_remove_input;
  663. /* request io port */
  664. list_for_each_entry_reverse(io, &spic_dev.ioports, list) {
  665. if (request_region(io->io1.minimum, io->io1.address_length,
  666. "Sony Programmable I/O Device")) {
  667. printk( KERN_NOTICE "[%s] I/O port1: 0x%.4x (0x%.4x) + 0x%.2x\n",
  668. KBUILD_MODNAME,
  669. io->io1.minimum,
  670. io->io1.maximum,
  671. io->io1.address_length
  672. );
  673. /* Type 1 have 2 ioports */
  674. if (io->io2.minimum) {
  675. if (request_region(io->io2.minimum,
  676. io->io2.address_length,
  677. "Sony Programmable I/O Device")) {
  678. printk( KERN_NOTICE "[%s] I/O port2: 0x%.4x (0x%.4x) + 0x%.2x\n",
  679. KBUILD_MODNAME,
  680. io->io2.minimum,
  681. io->io2.maximum,
  682. io->io2.address_length
  683. );
  684. spic_dev.cur_ioport = io;
  685. break;
  686. }
  687. else {
  688. printk( KERN_ERR "[%s] Unable to get I/O port2: 0x%.4x (0x%.4x) + 0x%.2x\n",
  689. KBUILD_MODNAME,
  690. io->io2.minimum,
  691. io->io2.maximum,
  692. io->io2.address_length
  693. );
  694. release_region( io->io1.minimum, io->io1.address_length );
  695. }
  696. }
  697. else {
  698. spic_dev.cur_ioport = io;
  699. break;
  700. }
  701. }
  702. }
  703. if (!spic_dev.cur_ioport) {
  704. pr_err( "[%s]Failed to request_region\n", KBUILD_MODNAME );
  705. result = -ENODEV;
  706. goto err_remove_compat;
  707. }
  708. /* request IRQ */
  709. list_for_each_entry_reverse(irq, &spic_dev.interrupts, list) {
  710. if( !request_irq(irq->irq.interrupts[0], sony_pic_irq_handler, 0, KBUILD_MODNAME, &spic_dev) ){
  711. printk( KERN_NOTICE "[%s] IRQ: %d - triggering: %d - polarity: %d - shr: %d\n",
  712. KBUILD_MODNAME,
  713. irq->irq.interrupts[0],
  714. irq->irq.triggering,
  715. irq->irq.polarity,
  716. irq->irq.shareable
  717. );
  718. spic_dev.cur_irq = irq;
  719. break;
  720. }
  721. }
  722. if (!spic_dev.cur_irq) {
  723. pr_err( "[%s]Failed to request_irq\n", KBUILD_MODNAME );
  724. result = -ENODEV;
  725. goto err_release_region;
  726. }
  727. /* set resource status _SRS */
  728. result = sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq);
  729. if ( result ) {
  730. printk( KERN_ERR "[%s] Couldn't enable device\n", KBUILD_MODNAME );
  731. goto err_free_irq;
  732. }
  733. spic_dev.bluetooth_power = -1;
  734. /* create device attributes */
  735. result = sony_pf_add();
  736. if (result) goto err_disable_device;
  737. result = sysfs_create_group(&sony_pf_device->dev.kobj, &spic_attribute_group);
  738. if (result) goto err_remove_pf;
  739. pr_info( "[%s] SPIC setup done.\n", KBUILD_MODNAME );
  740. return 0;
  741. err_remove_pf:
  742. sony_pf_remove();
  743. err_disable_device:
  744. sony_pic_disable(device);
  745. err_free_irq:
  746. free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
  747. err_release_region:
  748. release_region(spic_dev.cur_ioport->io1.minimum, spic_dev.cur_ioport->io1.address_length);
  749. if (spic_dev.cur_ioport->io2.minimum)
  750. release_region(spic_dev.cur_ioport->io2.minimum, spic_dev.cur_ioport->io2.address_length);
  751. err_remove_compat:
  752. sonypi_compat_exit();
  753. err_remove_input:
  754. vgnux_unregister_input();
  755. err_free_resources:
  756. list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) {
  757. list_del(&io->list);
  758. kfree(io);
  759. }
  760. list_for_each_entry_safe(irq, tmp_irq, &spic_dev.interrupts, list) {
  761. list_del(&irq->list);
  762. kfree(irq);
  763. }
  764. spic_dev.cur_ioport = NULL;
  765. spic_dev.cur_irq = NULL;
  766. return result;
  767. }
  768. static int sony_pic_remove( struct acpi_device* device ){
  769. struct sony_pic_ioport *io, *tmp_io;
  770. struct sony_pic_irq *irq, *tmp_irq;
  771. if( sony_pic_disable(device) ) {
  772. pr_err("Couldn't disable device\n");
  773. return -ENXIO;
  774. }
  775. free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
  776. release_region(spic_dev.cur_ioport->io1.minimum, spic_dev.cur_ioport->io1.address_length);
  777. if (spic_dev.cur_ioport->io2.minimum)
  778. release_region(spic_dev.cur_ioport->io2.minimum, spic_dev.cur_ioport->io2.address_length);
  779. sonypi_compat_exit();
  780. vgnux_unregister_input();
  781. /* pf attrs */
  782. sysfs_remove_group(&sony_pf_device->dev.kobj, &spic_attribute_group);
  783. sony_pf_remove();
  784. list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) {
  785. list_del(&io->list);
  786. kfree(io);
  787. }
  788. list_for_each_entry_safe(irq, tmp_irq, &spic_dev.interrupts, list) {
  789. list_del(&irq->list);
  790. kfree(irq);
  791. }
  792. spic_dev.cur_ioport = NULL;
  793. spic_dev.cur_irq = NULL;
  794. printk( KERN_NOTICE "[%s] "SONY_PIC_DRIVER_NAME " removed.\n", KBUILD_MODNAME );
  795. return 0;
  796. }
  797. #ifdef CONFIG_PM_SLEEP
  798. static int sony_pic_suspend( struct device* dev ){
  799. if( sony_pic_disable(to_acpi_device(dev)) ) return -ENXIO;
  800. return 0;
  801. }
  802. static int sony_pic_resume( struct device* dev ){
  803. sony_pic_enable( to_acpi_device(dev), spic_dev.cur_ioport, spic_dev.cur_irq );
  804. return 0;
  805. }
  806. #endif
  807. /********************
  808. * MODULE INIT *
  809. ********************/
  810. static int __init onLoad( void ){
  811. int result = 0;
  812. printk( KERN_NOTICE "%s is here.\n", KBUILD_MODNAME );
  813. if( !dmi_check_system( sonypi_dmi_table ) ){
  814. printk( KERN_NOTICE "[%s] Compatable hardware not found.\n", KBUILD_MODNAME );
  815. return -ENODEV;
  816. }
  817. result = acpi_bus_register_driver( &sony_pic_driver );
  818. if( result ) printk( KERN_ERR "[%s] Unable to register SPIC driver\n", KBUILD_MODNAME );
  819. return result;
  820. }
  821. static void __exit onUnload( void ){
  822. acpi_bus_unregister_driver( &sony_pic_driver );
  823. printk( KERN_NOTICE "%s has been unloaded.\n", KBUILD_MODNAME );
  824. }
  825. module_init( onLoad );
  826. module_exit( onUnload );
  827. MODULE_LICENSE("GPL");
  828. MODULE_DEVICE_TABLE( acpi, sony_pic_device_ids );