diff options
author | Erik Waling <erikw@acc.umu.se> | 2005-09-06 18:17:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-07 19:57:24 -0400 |
commit | d2052c1676a39cae101a81f3da8a4ade8b668c88 (patch) | |
tree | bc812cc27e1800a1849cdebb97a6dc0bba5b8c93 | |
parent | 2865cf001878d22d5fd12e5215621dffbcad76dc (diff) |
[PATCH] sonypi SPIC initialisation fix
Newer Sony VAIO models (VGN-S480, VGN-S460, VGN-S3XP etc) use a new method to
initialize the SPIC device. The new way to initialize (and disable) the
device comes directly from the AML code in the _CRS, _SRS and _DIS methods
from the DSDT table. This patch adds support for the new models.
Signed-off-by: Erik Waling <erikw@acc.umu.se>
Signed-off-by: Stelian Pop <stelian@popies.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | Documentation/sonypi.txt | 10 | ||||
-rw-r--r-- | drivers/char/sonypi.c | 117 | ||||
-rw-r--r-- | include/linux/sonypi.h | 2 |
3 files changed, 109 insertions, 20 deletions
diff --git a/Documentation/sonypi.txt b/Documentation/sonypi.txt index 0f3b2405d09e..c1237a925505 100644 --- a/Documentation/sonypi.txt +++ b/Documentation/sonypi.txt | |||
@@ -99,6 +99,7 @@ statically linked into the kernel). Those options are: | |||
99 | SONYPI_MEYE_MASK 0x0400 | 99 | SONYPI_MEYE_MASK 0x0400 |
100 | SONYPI_MEMORYSTICK_MASK 0x0800 | 100 | SONYPI_MEMORYSTICK_MASK 0x0800 |
101 | SONYPI_BATTERY_MASK 0x1000 | 101 | SONYPI_BATTERY_MASK 0x1000 |
102 | SONYPI_WIRELESS_MASK 0x2000 | ||
102 | 103 | ||
103 | useinput: if set (which is the default) two input devices are | 104 | useinput: if set (which is the default) two input devices are |
104 | created, one which interprets the jogdial events as | 105 | created, one which interprets the jogdial events as |
@@ -137,6 +138,15 @@ Bugs: | |||
137 | speed handling etc). Use ACPI instead of APM if it works on your | 138 | speed handling etc). Use ACPI instead of APM if it works on your |
138 | laptop. | 139 | laptop. |
139 | 140 | ||
141 | - sonypi lacks the ability to distinguish between certain key | ||
142 | events on some models. | ||
143 | |||
144 | - some models with the nvidia card (geforce go 6200 tc) uses a | ||
145 | different way to adjust the backlighting of the screen. There | ||
146 | is a userspace utility to adjust the brightness on those models, | ||
147 | which can be downloaded from | ||
148 | http://www.acc.umu.se/~erikw/program/smartdimmer-0.1.tar.bz2 | ||
149 | |||
140 | - since all development was done by reverse engineering, there is | 150 | - since all development was done by reverse engineering, there is |
141 | _absolutely no guarantee_ that this driver will not crash your | 151 | _absolutely no guarantee_ that this driver will not crash your |
142 | laptop. Permanently. | 152 | laptop. Permanently. |
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index cefbe985e55c..35cf1edbc179 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c | |||
@@ -98,12 +98,13 @@ MODULE_PARM_DESC(useinput, | |||
98 | 98 | ||
99 | #define SONYPI_DEVICE_MODEL_TYPE1 1 | 99 | #define SONYPI_DEVICE_MODEL_TYPE1 1 |
100 | #define SONYPI_DEVICE_MODEL_TYPE2 2 | 100 | #define SONYPI_DEVICE_MODEL_TYPE2 2 |
101 | #define SONYPI_DEVICE_MODEL_TYPE3 3 | ||
101 | 102 | ||
102 | /* type1 models use those */ | 103 | /* type1 models use those */ |
103 | #define SONYPI_IRQ_PORT 0x8034 | 104 | #define SONYPI_IRQ_PORT 0x8034 |
104 | #define SONYPI_IRQ_SHIFT 22 | 105 | #define SONYPI_IRQ_SHIFT 22 |
105 | #define SONYPI_BASE 0x50 | 106 | #define SONYPI_TYPE1_BASE 0x50 |
106 | #define SONYPI_G10A (SONYPI_BASE+0x14) | 107 | #define SONYPI_G10A (SONYPI_TYPE1_BASE+0x14) |
107 | #define SONYPI_TYPE1_REGION_SIZE 0x08 | 108 | #define SONYPI_TYPE1_REGION_SIZE 0x08 |
108 | #define SONYPI_TYPE1_EVTYPE_OFFSET 0x04 | 109 | #define SONYPI_TYPE1_EVTYPE_OFFSET 0x04 |
109 | 110 | ||
@@ -114,6 +115,13 @@ MODULE_PARM_DESC(useinput, | |||
114 | #define SONYPI_TYPE2_REGION_SIZE 0x20 | 115 | #define SONYPI_TYPE2_REGION_SIZE 0x20 |
115 | #define SONYPI_TYPE2_EVTYPE_OFFSET 0x12 | 116 | #define SONYPI_TYPE2_EVTYPE_OFFSET 0x12 |
116 | 117 | ||
118 | /* type3 series specifics */ | ||
119 | #define SONYPI_TYPE3_BASE 0x40 | ||
120 | #define SONYPI_TYPE3_GID2 (SONYPI_TYPE3_BASE+0x48) /* 16 bits */ | ||
121 | #define SONYPI_TYPE3_MISC (SONYPI_TYPE3_BASE+0x6d) /* 8 bits */ | ||
122 | #define SONYPI_TYPE3_REGION_SIZE 0x20 | ||
123 | #define SONYPI_TYPE3_EVTYPE_OFFSET 0x12 | ||
124 | |||
117 | /* battery / brightness addresses */ | 125 | /* battery / brightness addresses */ |
118 | #define SONYPI_BAT_FLAGS 0x81 | 126 | #define SONYPI_BAT_FLAGS 0x81 |
119 | #define SONYPI_LCD_LIGHT 0x96 | 127 | #define SONYPI_LCD_LIGHT 0x96 |
@@ -159,6 +167,10 @@ static struct sonypi_ioport_list sonypi_type2_ioport_list[] = { | |||
159 | { 0x0, 0x0 } | 167 | { 0x0, 0x0 } |
160 | }; | 168 | }; |
161 | 169 | ||
170 | /* same as in type 2 models */ | ||
171 | static struct sonypi_ioport_list *sonypi_type3_ioport_list = | ||
172 | sonypi_type2_ioport_list; | ||
173 | |||
162 | /* The set of possible interrupts */ | 174 | /* The set of possible interrupts */ |
163 | struct sonypi_irq_list { | 175 | struct sonypi_irq_list { |
164 | u16 irq; | 176 | u16 irq; |
@@ -180,6 +192,9 @@ static struct sonypi_irq_list sonypi_type2_irq_list[] = { | |||
180 | { 0, 0x00 } /* no IRQ, 0x00 in SIRQ in AML */ | 192 | { 0, 0x00 } /* no IRQ, 0x00 in SIRQ in AML */ |
181 | }; | 193 | }; |
182 | 194 | ||
195 | /* same as in type2 models */ | ||
196 | static struct sonypi_irq_list *sonypi_type3_irq_list = sonypi_type2_irq_list; | ||
197 | |||
183 | #define SONYPI_CAMERA_BRIGHTNESS 0 | 198 | #define SONYPI_CAMERA_BRIGHTNESS 0 |
184 | #define SONYPI_CAMERA_CONTRAST 1 | 199 | #define SONYPI_CAMERA_CONTRAST 1 |
185 | #define SONYPI_CAMERA_HUE 2 | 200 | #define SONYPI_CAMERA_HUE 2 |
@@ -223,6 +238,7 @@ static struct sonypi_irq_list sonypi_type2_irq_list[] = { | |||
223 | #define SONYPI_MEYE_MASK 0x00000400 | 238 | #define SONYPI_MEYE_MASK 0x00000400 |
224 | #define SONYPI_MEMORYSTICK_MASK 0x00000800 | 239 | #define SONYPI_MEMORYSTICK_MASK 0x00000800 |
225 | #define SONYPI_BATTERY_MASK 0x00001000 | 240 | #define SONYPI_BATTERY_MASK 0x00001000 |
241 | #define SONYPI_WIRELESS_MASK 0x00002000 | ||
226 | 242 | ||
227 | struct sonypi_event { | 243 | struct sonypi_event { |
228 | u8 data; | 244 | u8 data; |
@@ -305,6 +321,13 @@ static struct sonypi_event sonypi_blueev[] = { | |||
305 | { 0, 0 } | 321 | { 0, 0 } |
306 | }; | 322 | }; |
307 | 323 | ||
324 | /* The set of possible wireless events */ | ||
325 | static struct sonypi_event sonypi_wlessev[] = { | ||
326 | { 0x59, SONYPI_EVENT_WIRELESS_ON }, | ||
327 | { 0x5a, SONYPI_EVENT_WIRELESS_OFF }, | ||
328 | { 0, 0 } | ||
329 | }; | ||
330 | |||
308 | /* The set of possible back button events */ | 331 | /* The set of possible back button events */ |
309 | static struct sonypi_event sonypi_backev[] = { | 332 | static struct sonypi_event sonypi_backev[] = { |
310 | { 0x20, SONYPI_EVENT_BACK_PRESSED }, | 333 | { 0x20, SONYPI_EVENT_BACK_PRESSED }, |
@@ -391,6 +414,12 @@ static struct sonypi_eventtypes { | |||
391 | { SONYPI_DEVICE_MODEL_TYPE2, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, | 414 | { SONYPI_DEVICE_MODEL_TYPE2, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, |
392 | { SONYPI_DEVICE_MODEL_TYPE2, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, | 415 | { SONYPI_DEVICE_MODEL_TYPE2, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, |
393 | 416 | ||
417 | { SONYPI_DEVICE_MODEL_TYPE3, 0, 0xffffffff, sonypi_releaseev }, | ||
418 | { SONYPI_DEVICE_MODEL_TYPE3, 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, | ||
419 | { SONYPI_DEVICE_MODEL_TYPE3, 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev }, | ||
420 | { SONYPI_DEVICE_MODEL_TYPE3, 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, | ||
421 | { SONYPI_DEVICE_MODEL_TYPE3, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, | ||
422 | { SONYPI_DEVICE_MODEL_TYPE3, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, | ||
394 | { 0 } | 423 | { 0 } |
395 | }; | 424 | }; |
396 | 425 | ||
@@ -563,6 +592,23 @@ static void sonypi_type2_srs(void) | |||
563 | udelay(10); | 592 | udelay(10); |
564 | } | 593 | } |
565 | 594 | ||
595 | static void sonypi_type3_srs(void) | ||
596 | { | ||
597 | u16 v16; | ||
598 | u8 v8; | ||
599 | |||
600 | /* This model type uses the same initialiazation of | ||
601 | * the embedded controller as the type2 models. */ | ||
602 | sonypi_type2_srs(); | ||
603 | |||
604 | /* Initialization of PCI config space of the LPC interface bridge. */ | ||
605 | v16 = (sonypi_device.ioport1 & 0xFFF0) | 0x01; | ||
606 | pci_write_config_word(sonypi_device.dev, SONYPI_TYPE3_GID2, v16); | ||
607 | pci_read_config_byte(sonypi_device.dev, SONYPI_TYPE3_MISC, &v8); | ||
608 | v8 = (v8 & 0xCF) | 0x10; | ||
609 | pci_write_config_byte(sonypi_device.dev, SONYPI_TYPE3_MISC, v8); | ||
610 | } | ||
611 | |||
566 | /* Disables the device - this comes from the AML code in the ACPI bios */ | 612 | /* Disables the device - this comes from the AML code in the ACPI bios */ |
567 | static void sonypi_type1_dis(void) | 613 | static void sonypi_type1_dis(void) |
568 | { | 614 | { |
@@ -587,6 +633,13 @@ static void sonypi_type2_dis(void) | |||
587 | printk(KERN_WARNING "ec_write failed\n"); | 633 | printk(KERN_WARNING "ec_write failed\n"); |
588 | } | 634 | } |
589 | 635 | ||
636 | static void sonypi_type3_dis(void) | ||
637 | { | ||
638 | sonypi_type2_dis(); | ||
639 | udelay(10); | ||
640 | pci_write_config_word(sonypi_device.dev, SONYPI_TYPE3_GID2, 0); | ||
641 | } | ||
642 | |||
590 | static u8 sonypi_call1(u8 dev) | 643 | static u8 sonypi_call1(u8 dev) |
591 | { | 644 | { |
592 | u8 v1, v2; | 645 | u8 v1, v2; |
@@ -1067,10 +1120,17 @@ static struct miscdevice sonypi_misc_device = { | |||
1067 | 1120 | ||
1068 | static void sonypi_enable(unsigned int camera_on) | 1121 | static void sonypi_enable(unsigned int camera_on) |
1069 | { | 1122 | { |
1070 | if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) | 1123 | switch (sonypi_device.model) { |
1071 | sonypi_type2_srs(); | 1124 | case SONYPI_DEVICE_MODEL_TYPE1: |
1072 | else | ||
1073 | sonypi_type1_srs(); | 1125 | sonypi_type1_srs(); |
1126 | break; | ||
1127 | case SONYPI_DEVICE_MODEL_TYPE2: | ||
1128 | sonypi_type2_srs(); | ||
1129 | break; | ||
1130 | case SONYPI_DEVICE_MODEL_TYPE3: | ||
1131 | sonypi_type3_srs(); | ||
1132 | break; | ||
1133 | } | ||
1074 | 1134 | ||
1075 | sonypi_call1(0x82); | 1135 | sonypi_call1(0x82); |
1076 | sonypi_call2(0x81, 0xff); | 1136 | sonypi_call2(0x81, 0xff); |
@@ -1094,10 +1154,18 @@ static int sonypi_disable(void) | |||
1094 | if (!SONYPI_ACPI_ACTIVE && fnkeyinit) | 1154 | if (!SONYPI_ACPI_ACTIVE && fnkeyinit) |
1095 | outb(0xf1, 0xb2); | 1155 | outb(0xf1, 0xb2); |
1096 | 1156 | ||
1097 | if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) | 1157 | switch (sonypi_device.model) { |
1098 | sonypi_type2_dis(); | 1158 | case SONYPI_DEVICE_MODEL_TYPE1: |
1099 | else | ||
1100 | sonypi_type1_dis(); | 1159 | sonypi_type1_dis(); |
1160 | break; | ||
1161 | case SONYPI_DEVICE_MODEL_TYPE2: | ||
1162 | sonypi_type2_dis(); | ||
1163 | break; | ||
1164 | case SONYPI_DEVICE_MODEL_TYPE3: | ||
1165 | sonypi_type3_dis(); | ||
1166 | break; | ||
1167 | } | ||
1168 | |||
1101 | return 0; | 1169 | return 0; |
1102 | } | 1170 | } |
1103 | 1171 | ||
@@ -1143,12 +1211,16 @@ static int __devinit sonypi_probe(void) | |||
1143 | struct sonypi_irq_list *irq_list; | 1211 | struct sonypi_irq_list *irq_list; |
1144 | struct pci_dev *pcidev; | 1212 | struct pci_dev *pcidev; |
1145 | 1213 | ||
1146 | pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | 1214 | if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, |
1147 | PCI_DEVICE_ID_INTEL_82371AB_3, NULL); | 1215 | PCI_DEVICE_ID_INTEL_82371AB_3, NULL))) |
1216 | sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE1; | ||
1217 | else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
1218 | PCI_DEVICE_ID_INTEL_ICH6_1, NULL))) | ||
1219 | sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3; | ||
1220 | else | ||
1221 | sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2; | ||
1148 | 1222 | ||
1149 | sonypi_device.dev = pcidev; | 1223 | sonypi_device.dev = pcidev; |
1150 | sonypi_device.model = pcidev ? | ||
1151 | SONYPI_DEVICE_MODEL_TYPE1 : SONYPI_DEVICE_MODEL_TYPE2; | ||
1152 | 1224 | ||
1153 | spin_lock_init(&sonypi_device.fifo_lock); | 1225 | spin_lock_init(&sonypi_device.fifo_lock); |
1154 | sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL, | 1226 | sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL, |
@@ -1176,16 +1248,22 @@ static int __devinit sonypi_probe(void) | |||
1176 | goto out_miscreg; | 1248 | goto out_miscreg; |
1177 | } | 1249 | } |
1178 | 1250 | ||
1179 | if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) { | 1251 | |
1252 | if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) { | ||
1253 | ioport_list = sonypi_type1_ioport_list; | ||
1254 | sonypi_device.region_size = SONYPI_TYPE1_REGION_SIZE; | ||
1255 | sonypi_device.evtype_offset = SONYPI_TYPE1_EVTYPE_OFFSET; | ||
1256 | irq_list = sonypi_type1_irq_list; | ||
1257 | } else if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) { | ||
1180 | ioport_list = sonypi_type2_ioport_list; | 1258 | ioport_list = sonypi_type2_ioport_list; |
1181 | sonypi_device.region_size = SONYPI_TYPE2_REGION_SIZE; | 1259 | sonypi_device.region_size = SONYPI_TYPE2_REGION_SIZE; |
1182 | sonypi_device.evtype_offset = SONYPI_TYPE2_EVTYPE_OFFSET; | 1260 | sonypi_device.evtype_offset = SONYPI_TYPE2_EVTYPE_OFFSET; |
1183 | irq_list = sonypi_type2_irq_list; | 1261 | irq_list = sonypi_type2_irq_list; |
1184 | } else { | 1262 | } else { |
1185 | ioport_list = sonypi_type1_ioport_list; | 1263 | ioport_list = sonypi_type3_ioport_list; |
1186 | sonypi_device.region_size = SONYPI_TYPE1_REGION_SIZE; | 1264 | sonypi_device.region_size = SONYPI_TYPE3_REGION_SIZE; |
1187 | sonypi_device.evtype_offset = SONYPI_TYPE1_EVTYPE_OFFSET; | 1265 | sonypi_device.evtype_offset = SONYPI_TYPE3_EVTYPE_OFFSET; |
1188 | irq_list = sonypi_type1_irq_list; | 1266 | irq_list = sonypi_type3_irq_list; |
1189 | } | 1267 | } |
1190 | 1268 | ||
1191 | for (i = 0; ioport_list[i].port1; i++) { | 1269 | for (i = 0; ioport_list[i].port1; i++) { |
@@ -1274,11 +1352,10 @@ static int __devinit sonypi_probe(void) | |||
1274 | 1352 | ||
1275 | printk(KERN_INFO "sonypi: Sony Programmable I/O Controller Driver" | 1353 | printk(KERN_INFO "sonypi: Sony Programmable I/O Controller Driver" |
1276 | "v%s.\n", SONYPI_DRIVER_VERSION); | 1354 | "v%s.\n", SONYPI_DRIVER_VERSION); |
1277 | printk(KERN_INFO "sonypi: detected %s model, " | 1355 | printk(KERN_INFO "sonypi: detected type%d model, " |
1278 | "verbose = %d, fnkeyinit = %s, camera = %s, " | 1356 | "verbose = %d, fnkeyinit = %s, camera = %s, " |
1279 | "compat = %s, mask = 0x%08lx, useinput = %s, acpi = %s\n", | 1357 | "compat = %s, mask = 0x%08lx, useinput = %s, acpi = %s\n", |
1280 | (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) ? | 1358 | sonypi_device.model, |
1281 | "type1" : "type2", | ||
1282 | verbose, | 1359 | verbose, |
1283 | fnkeyinit ? "on" : "off", | 1360 | fnkeyinit ? "on" : "off", |
1284 | camera ? "on" : "off", | 1361 | camera ? "on" : "off", |
diff --git a/include/linux/sonypi.h b/include/linux/sonypi.h index 768cbba617d0..f56d24734950 100644 --- a/include/linux/sonypi.h +++ b/include/linux/sonypi.h | |||
@@ -99,6 +99,8 @@ | |||
99 | #define SONYPI_EVENT_BATTERY_INSERT 57 | 99 | #define SONYPI_EVENT_BATTERY_INSERT 57 |
100 | #define SONYPI_EVENT_BATTERY_REMOVE 58 | 100 | #define SONYPI_EVENT_BATTERY_REMOVE 58 |
101 | #define SONYPI_EVENT_FNKEY_RELEASED 59 | 101 | #define SONYPI_EVENT_FNKEY_RELEASED 59 |
102 | #define SONYPI_EVENT_WIRELESS_ON 60 | ||
103 | #define SONYPI_EVENT_WIRELESS_OFF 61 | ||
102 | 104 | ||
103 | /* get/set brightness */ | 105 | /* get/set brightness */ |
104 | #define SONYPI_IOCGBRT _IOR('v', 0, __u8) | 106 | #define SONYPI_IOCGBRT _IOR('v', 0, __u8) |